From bb80906868d26b9eec6ecd2ed2d7593ccbe88ae5 Mon Sep 17 00:00:00 2001 From: rpkak Date: Sun, 28 Dec 2025 21:48:43 +0100 Subject: [PATCH 001/215] Fix some counting errors related to std.Progress in the compiler --- src/Compilation.zig | 9 ++++++++- src/Zcu/PerThread.zig | 1 + src/link/Coff.zig | 4 +++- src/link/Elf2.zig | 6 ++++-- src/link/Wasm.zig | 1 + 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 3e3658021438b7aa518282c77c3d04bba3d269b9..8fb16e52c566de5e85771da874c3c723b3c1d411 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2911,7 +2911,14 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // The linker progress node is set up here instead of in `performAllTheWork`, because // we also want it around during `flush`. if (comp.bin_file) |lf| { - comp.link_prog_node = main_progress_node.start("Linking", 0); + // mirrors logic in `Compilation.flush`: + // For llvm: "LLVM Emit Object" and "Parse Object" with the zcu object + // Always: flush of the linker + const initial_estimated_total: usize = if (comp.zcu) |zcu| + if (zcu.llvm_object) |_| 3 else 1 + else + 1; + comp.link_prog_node = main_progress_node.start("Linking", initial_estimated_total); lf.startProgress(comp.link_prog_node); } defer if (comp.bin_file) |lf| { diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 62f11a83f671cc7b2ea3b20c7b6e0e94f342d354..e708f35ff25102fa99655f4fb99d9396df198215 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -876,6 +876,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { const old_line = old_zir.getDeclaration(old_inst).src_line; const new_line = new_zir.getDeclaration(new_inst).src_line; if (old_line != new_line) { + comp.link_prog_node.increaseEstimatedTotalItems(1); try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index }); } }, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 756c4c8892b29f54be05456d12277aa49bc3a444..aff6d72fb3d956490ce1c0dc766fce9f1b192cb5 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -5886,7 +5886,9 @@ pub fn flush( prog_node: std.Progress.Node, ) link.Error!void { _ = arena; - _ = prog_node; + const sub_prog_node = prog_node.start("COFF Flush", 0); + defer sub_prog_node.end(); + const comp = coff.base.comp; // TODO: When https://github.com/ziglang/zig/issues/23617 is in, diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 2c6aefe7bcbc8fc02fb9c46e3c12905e4d640826..62d152f057822e27cf1cce1eaa5cf0aa176a706d 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -5224,7 +5224,7 @@ fn loadObject( .first_symbol_reloc = .none, .first_got_reloc = .none, }; - elf.synth_prog_node.increaseEstimatedTotalItems(1); + elf.input_prog_node.increaseEstimatedTotalItems(1); } var symmap: std.ArrayList(Symbol.Id) = .empty; defer symmap.deinit(gpa); @@ -7105,9 +7105,11 @@ pub fn flush( ) link.Error!void { const comp = elf.base.comp; const diags = &comp.link_diags; - _ = prog_node; _ = arena; + const sub_prog_node = prog_node.start("ELF Flush", 0); + defer sub_prog_node.end(); + if (comp.config.output_mode == .Exe) { var any_undef = false; for (elf.globals.strong_undef.keys()) |name| { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 40c3e412b4ac88c019cf6885e2d9e4bb1e2b329e..1894440ee1378807867cee8e4150c09161994f0e 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3398,6 +3398,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { const tracy = trace(@src()); defer tracy.end(); + prog_node.increaseEstimatedTotalItems(1); const sub_prog_node = prog_node.start("Wasm Prelink", 0); defer sub_prog_node.end(); -- 2.54.0 From bcaf025a6241b80826dfc13aca7ea4a56c467f55 Mon Sep 17 00:00:00 2001 From: rpkak Date: Mon, 13 Jul 2026 11:37:57 +0200 Subject: [PATCH 002/215] Prelink Progress Node --- src/Compilation.zig | 16 +++++++++++----- src/link.zig | 2 +- src/link/Coff.zig | 4 +++- src/link/Elf2.zig | 4 +++- src/link/Wasm.zig | 1 - 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 8fb16e52c566de5e85771da874c3c723b3c1d411..b062f41ae84d02fe38bb66c454c7eb2f883ba49f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2912,12 +2912,18 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // we also want it around during `flush`. if (comp.bin_file) |lf| { // mirrors logic in `Compilation.flush`: + // Always: linker flush + var initial_estimated_total: usize = 1; + const llvm = if (comp.zcu) |zcu| zcu.llvm_object != null else false; // For llvm: "LLVM Emit Object" and "Parse Object" with the zcu object - // Always: flush of the linker - const initial_estimated_total: usize = if (comp.zcu) |zcu| - if (zcu.llvm_object) |_| 3 else 1 - else - 1; + if (llvm) { + initial_estimated_total += 2; + } + // Prelink + if (!lf.post_prelink or llvm) { + initial_estimated_total += 1; + } + comp.link_prog_node = main_progress_node.start("Linking", initial_estimated_total); lf.startProgress(comp.link_prog_node); } diff --git a/src/link.zig b/src/link.zig index f5489c19d4454110a6fbdcc3c132dd34d2dcf996..ccba1ea2df3ed1c561022de0b170001ab9bcb7ed 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1243,7 +1243,7 @@ pub const File = struct { dev.check(tag.devFeature()); try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); }, - else => {}, + else => base.comp.link_prog_node.completeOne(), } base.post_prelink = true; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index aff6d72fb3d956490ce1c0dc766fce9f1b192cb5..4ba00de0ee41b2f559cd44402fe851aa7cebe7bb 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -5370,7 +5370,9 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInp } pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { - _ = prog_node; + const sub_prog_node = prog_node.start("COFF Prelink", 0); + defer sub_prog_node.end(); + const base = coff.base; const comp = base.comp; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 62d152f057822e27cf1cce1eaa5cf0aa176a706d..706b1387b31d5533ceb9a670984f1fbaf4337276 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -5749,7 +5749,9 @@ fn updateInitFiniArraySectionSize( } pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void { - _ = prog_node; + const sub_prog_node = prog_node.start("ELF Prelink", 0); + defer sub_prog_node.end(); + const diags = &elf.base.comp.link_diags; elf.prelinkInner() catch |err| switch (err) { error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 1894440ee1378807867cee8e4150c09161994f0e..40c3e412b4ac88c019cf6885e2d9e4bb1e2b329e 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3398,7 +3398,6 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { const tracy = trace(@src()); defer tracy.end(); - prog_node.increaseEstimatedTotalItems(1); const sub_prog_node = prog_node.start("Wasm Prelink", 0); defer sub_prog_node.end(); -- 2.54.0 From 97262708460d552e102f003cc3202b40fe744e1d Mon Sep 17 00:00:00 2001 From: Akshay Trivedi Date: Sun, 14 Jun 2026 17:24:36 -0700 Subject: [PATCH 003/215] handle ConnectionRefused in posixConnectUnix --- lib/std/Io/Threaded.zig | 1 + lib/std/Io/net.zig | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index b02453c1e34cacd3f5b8417156a63022d11f8a89..b3cc49cd3f792f3a3c70e086d9c9bf2034abc56c 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -12124,6 +12124,7 @@ fn posixConnectUnix( .NOTDIR => return error.NotDir, .ROFS => return error.ReadOnlyFileSystem, .PERM => return error.PermissionDenied, + .CONNREFUSED => return error.ConnectionRefused, .BADF => |err| return errnoBug(err), // File descriptor used after closed. .CONNABORTED => |err| return errnoBug(err), diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index a546552cb9c7bb24ced83e88fbae4946f21a7061..d7454a9d5db4d704f29fed8147da260562e3e660 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -901,6 +901,7 @@ pub const UnixAddress = struct { ReadOnlyFileSystem, WouldBlock, NetworkDown, + ConnectionRefused, } || Io.Cancelable || Io.UnexpectedError; pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream { -- 2.54.0 From 6c25d2bd58e4b5a002a7d1cd2882dd4e7ef23b6f Mon Sep 17 00:00:00 2001 From: Thibault Leclercq Date: Fri, 17 Jul 2026 18:27:47 +0200 Subject: [PATCH 004/215] std.debug.SelfInfo.Elf: clear unwind cache when rebuilding module list --- lib/std/debug/SelfInfo/Elf.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 7a81b4cba894fd238d72e5e1c74cdc3df8ae176a..eb60162dcb405709a7468e97ea4b755aaefe2d90 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -428,6 +428,9 @@ fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum // Rebuild module list with the exclusive lock. { errdefer si.rwlock.unlock(io); + if (si.unwind_cache) |cache| { + @memset(cache, .empty); + } for (si.modules.items) |*mod| { unwind: { const u = &(mod.unwind orelse break :unwind catch break :unwind); -- 2.54.0 From ae4e835a662a3b8c512511b87f4a44065e26dbb7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 19 Jul 2026 17:22:10 -0700 Subject: [PATCH 005/215] std.lang: rename OptimizeMode to Optimize and remove "release" from the enum tag names. no functional change, however, despite the addition of backwards-compatibile declarations in this patch, it is breaking because expressions that use `==` or `!=` operators will not able to use the deprecated names. I predict these names to survive until the 1.0 tag without any more breakage. --- build.zig | 16 ++--- lib/c/malloc.zig | 4 +- lib/compiler/Maker.zig | 6 +- lib/compiler/Maker/Step/TranslateC.zig | 6 +- lib/compiler/Maker/WebServer.zig | 2 +- lib/compiler/aro/aro/Diagnostics.zig | 2 +- lib/compiler/aro/main.zig | 2 +- lib/compiler/std-docs.zig | 4 +- lib/compiler/translate-c/main.zig | 2 +- lib/compiler_rt/memcpy.zig | 2 +- lib/compiler_rt/memmove.zig | 2 +- lib/docs/wasm/markdown/Document.zig | 2 +- lib/fuzzer.zig | 6 +- lib/std/Build.zig | 60 ++++++++++++------- lib/std/Build/Configuration.zig | 8 +-- lib/std/Build/Step/Compile.zig | 4 +- lib/std/Io/Dispatch.zig | 2 +- lib/std/Io/Threaded.zig | 12 ++-- lib/std/Io/Uring.zig | 2 +- lib/std/Random/benchmark.zig | 2 +- lib/std/c/darwin/dispatch.zig | 4 +- lib/std/compress/flate/Compress.zig | 2 +- lib/std/compress/flate/token.zig | 6 +- lib/std/crypto/25519/field.zig | 4 +- lib/std/crypto/benchmark.zig | 2 +- lib/std/crypto/ghash_polyval.zig | 10 ++-- lib/std/crypto/kangarootwelve.zig | 2 +- lib/std/crypto/keccak_p.zig | 4 +- lib/std/crypto/pcurves/p256/p256_64.zig | 34 +++++------ .../crypto/pcurves/p256/p256_scalar_64.zig | 34 +++++------ lib/std/crypto/pcurves/p384/p384_64.zig | 34 +++++------ .../crypto/pcurves/p384/p384_scalar_64.zig | 34 +++++------ .../crypto/pcurves/secp256k1/secp256k1_64.zig | 34 +++++------ .../pcurves/secp256k1/secp256k1_scalar_64.zig | 34 +++++------ lib/std/debug.zig | 14 ++--- lib/std/fmt.zig | 4 +- lib/std/fmt/float.zig | 2 +- lib/std/hash/benchmark.zig | 2 +- lib/std/heap/SafeAllocator.zig | 2 +- lib/std/http/test.zig | 18 +++--- lib/std/json/Stringify.zig | 6 +- lib/std/lang.zig | 40 +++++++++++-- lib/std/log.zig | 2 +- lib/std/math/hypot.zig | 8 +-- lib/std/process.zig | 4 +- lib/std/sort/block.zig | 2 +- lib/std/start.zig | 4 +- lib/std/std.zig | 4 +- lib/std/zig/Zir.zig | 2 +- src/Builtin.zig | 6 +- src/Compilation.zig | 40 ++++++------- src/Compilation/Config.zig | 14 ++--- src/Module.zig | 18 +++--- src/Sema.zig | 18 +++--- src/codegen/aarch64/Mir.zig | 4 +- src/codegen/c.zig | 8 +-- src/codegen/llvm.zig | 8 +-- src/codegen/llvm/FuncGen.zig | 8 +-- src/codegen/riscv64/CodeGen.zig | 6 +- src/codegen/sparc64/CodeGen.zig | 6 +- src/codegen/wasm/Mir.zig | 4 +- src/codegen/x86_64/CodeGen.zig | 8 +-- src/libs/libcxx.zig | 6 +- src/libs/libunwind.zig | 2 +- src/libs/mingw.zig | 4 +- src/link/C.zig | 2 +- src/link/Coff.zig | 16 ++--- src/link/Elf.zig | 2 +- src/link/Elf/ZigObject.zig | 8 +-- src/link/Elf2.zig | 8 +-- src/link/Lld.zig | 28 ++++----- src/link/MachO.zig | 2 +- src/link/MachO/ZigObject.zig | 8 +-- src/main.zig | 51 ++++++++-------- src/target.zig | 10 ++-- test/behavior/cast.zig | 2 +- test/behavior/floatop.zig | 2 +- test/behavior/int128.zig | 2 +- test/c_abi/main.zig | 6 +- .../invalid_member_of_builtin_enum.zig | 2 +- test/src/ErrorTrace.zig | 4 +- test/standalone/dependency_options/build.zig | 18 +++--- test/standalone/simple/build.zig | 10 ++-- test/tests.zig | 44 +++++++------- tools/doctest.zig | 6 +- tools/migrate_langref.zig | 4 +- 86 files changed, 470 insertions(+), 423 deletions(-) diff --git a/build.zig b/build.zig index 385d4d5b7e0288d79a07c4c2c314cb7e6bc30c5d..0bd1abe03359bdd5c84086c95286568022a53bc4 100644 --- a/build.zig +++ b/build.zig @@ -207,7 +207,7 @@ pub fn build(b: *std.Build) !void { const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: { if (strip == true) break :blk @as(u32, 0); - if (optimize != .Debug) break :blk 0; + if (optimize != .debug) break :blk 0; break :blk 4; }; @@ -256,7 +256,7 @@ pub fn build(b: *std.Build) !void { exe.root_module.link_libc = true; } - const is_debug = optimize == .Debug; + const is_debug = optimize == .debug; const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug; @@ -403,8 +403,8 @@ pub fn build(b: *std.Build) !void { if (tracy) |tracy_dir| { const tracy_mod = b.createModule(.{ .target = target, - // Always build Tracy in ReleaseFast so that it doesn't make Debug compiler builds unusable. - .optimize = .ReleaseFast, + // Always build Tracy in ReleaseFast so that it doesn't make -Odebug compiler builds unusable. + .optimize = .fast, .root_source_file = null, .link_libc = true, .link_libcpp = true, @@ -434,19 +434,19 @@ pub fn build(b: *std.Build) !void { var chosen_opt_modes_buf: [4]std.lang.OptimizeMode = undefined; var chosen_mode_index: usize = 0; if (!skip_debug) { - chosen_opt_modes_buf[chosen_mode_index] = .Debug; + chosen_opt_modes_buf[chosen_mode_index] = .debug; chosen_mode_index += 1; } if (!skip_release_safe) { - chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSafe; + chosen_opt_modes_buf[chosen_mode_index] = .safe; chosen_mode_index += 1; } if (!skip_release_fast) { - chosen_opt_modes_buf[chosen_mode_index] = .ReleaseFast; + chosen_opt_modes_buf[chosen_mode_index] = .fast; chosen_mode_index += 1; } if (!skip_release_small) { - chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSmall; + chosen_opt_modes_buf[chosen_mode_index] = .small; chosen_mode_index += 1; } const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index]; diff --git a/lib/c/malloc.zig b/lib/c/malloc.zig index 69f56641d0a26a9f4b68bbe75cc26de9203c6f1d..b9ba905440726fecbe7204ecd4e2d42bad198579 100644 --- a/lib/c/malloc.zig +++ b/lib/c/malloc.zig @@ -59,8 +59,8 @@ const Header = packed struct(u64) { } const safety = switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; const max_addr_bits = switch (safety) { true => 48, // Ensures space for Canary bits. diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 8b7c9a23edf2701ae1a84f45525d8bccf2a7a1f0..b5db0e68f7597a1e951900e8b741afb20521bcda 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -69,10 +69,10 @@ var debug_maker_leaks: bool = false; const AvoidableWebServer = if (builtin.single_threaded) void else WebServer; -const is_debug_mode = builtin.mode == .Debug; +const is_debug_mode = builtin.mode == .debug; const use_safe_allocator = switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; const InstallPaths = struct { diff --git a/lib/compiler/Maker/Step/TranslateC.zig b/lib/compiler/Maker/Step/TranslateC.zig index 94b90d65dc9a8ec48871d945924cb0e4461e80f4..79b8571ba6bfef3474ac68e2036f9bdbd1c2f5f8 100644 --- a/lib/compiler/Maker/Step/TranslateC.zig +++ b/lib/compiler/Maker/Step/TranslateC.zig @@ -49,9 +49,9 @@ pub fn make( const opt: ?OptimizeMode = switch (conf_tc.flags.optimize) { .debug, .default => null, // Skip since it's the default - .safe => .ReleaseSafe, - .fast => .ReleaseFast, - .small => .ReleaseSmall, + .safe => .safe, + .fast => .fast, + .small => .small, }; if (opt) |o| argv.appendAssumeCapacity(try arena.print("-O{t}", .{o})); diff --git a/lib/compiler/Maker/WebServer.zig b/lib/compiler/Maker/WebServer.zig index e47f18bb5f786aba032d64dc37f806200f15636c..1064519adc547a78c26bafc23351a640367178f5 100644 --- a/lib/compiler/Maker/WebServer.zig +++ b/lib/compiler/Maker/WebServer.zig @@ -501,7 +501,7 @@ fn serveRequest(ws: *WebServer, req: *http.Server.Request) !void { if (mem.eql(u8, target, "/main.js")) return serveLibFile(ws, req, "build-web/main.js", "application/javascript"); if (mem.eql(u8, target, "/style.css")) return serveLibFile(ws, req, "build-web/style.css", "text/css"); if (mem.eql(u8, target, "/time_report.css")) return serveLibFile(ws, req, "build-web/time_report.css", "text/css"); - if (mem.eql(u8, target, "/main.wasm")) return serveClientWasm(ws, req, if (debug) .Debug else .ReleaseFast); + if (mem.eql(u8, target, "/main.wasm")) return serveClientWasm(ws, req, if (debug) .debug else .fast); if (ws.fuzz) |*fuzz| { if (mem.eql(u8, target, "/sources.tar")) return fuzz.serveSourcesTar(req); diff --git a/lib/compiler/aro/aro/Diagnostics.zig b/lib/compiler/aro/aro/Diagnostics.zig index e2cd09c19f952da6c3e9507011443efea189cb5a..7bfa8be6efbdf7cb4af49d683e67bd2ab86fc068 100644 --- a/lib/compiler/aro/aro/Diagnostics.zig +++ b/lib/compiler/aro/aro/Diagnostics.zig @@ -510,7 +510,7 @@ pub fn formatArgs(w: *std.Io.Writer, fmt: []const u8, args: anytype) std.Io.Writ pub fn templateIndex(w: *std.Io.Writer, fmt: []const u8, template: []const u8) std.Io.Writer.Error!usize { const i = std.mem.indexOf(u8, fmt, template) orelse { - if (@import("builtin").mode == .Debug) { + if (@import("builtin").mode == .debug) { std.debug.panic("template `{s}` not found in format string `{s}`", .{ template, fmt }); } try w.print("template `{s}` not found in format string `{s}` (this is a bug in arocc)", .{ template, fmt }); diff --git a/lib/compiler/aro/main.zig b/lib/compiler/aro/main.zig index 7d946af0c54790f78c63b8efbe048a3c1f2af372..1bfc84caad7831b6132864158694e51b940080fc 100644 --- a/lib/compiler/aro/main.zig +++ b/lib/compiler/aro/main.zig @@ -40,7 +40,7 @@ pub fn main(init: process.Init.Minimal) u8 { defer threaded.deinit(); const io = threaded.io(); - const fast_exit = @import("builtin").mode != .Debug; + const fast_exit = @import("builtin").mode != .debug; const args = init.args.toSlice(arena) catch { std.debug.print("out of memory\n", .{}); diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index f41159adea3c864e0c02fe2402bbba70196dd91d..f53123ae925a7fb4d997e1b8c1a5463624077780 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -142,9 +142,9 @@ fn serveRequest(request: *std.http.Server.Request, context: *Context) !void { { try serveDocsFile(request, context, "docs/main.js", "application/javascript"); } else if (std.mem.eql(u8, request.head.target, "/main.wasm")) { - try serveWasm(request, context, .ReleaseFast); + try serveWasm(request, context, .fast); } else if (std.mem.eql(u8, request.head.target, "/debug/main.wasm")) { - try serveWasm(request, context, .Debug); + try serveWasm(request, context, .debug); } else if (std.mem.eql(u8, request.head.target, "/sources.tar") or std.mem.eql(u8, request.head.target, "/debug/sources.tar")) { diff --git a/lib/compiler/translate-c/main.zig b/lib/compiler/translate-c/main.zig index 95836a94519ecbae20eea20f63b03d161301376c..e5c3961076a2daa2ec4a119c5903f175db96857c 100644 --- a/lib/compiler/translate-c/main.zig +++ b/lib/compiler/translate-c/main.zig @@ -9,7 +9,7 @@ const compiler_util = @import("../util.zig"); const Translator = @import("Translator.zig"); -const fast_exit = @import("builtin").mode != .Debug; +const fast_exit = @import("builtin").mode != .debug; pub fn main(init: process.Init) u8 { const gpa = init.gpa; diff --git a/lib/compiler_rt/memcpy.zig b/lib/compiler_rt/memcpy.zig index bb3c91eea83601771be7a61f1f4a8cd3d20e2249..b75f40ea4324448579f97f499cfb76493386adcf 100644 --- a/lib/compiler_rt/memcpy.zig +++ b/lib/compiler_rt/memcpy.zig @@ -11,7 +11,7 @@ comptime { .visibility = compiler_rt.visibility, }; - if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64) + if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64) @export(&memcpySmall, export_options) else @export(&memcpyFast, export_options); diff --git a/lib/compiler_rt/memmove.zig b/lib/compiler_rt/memmove.zig index ad501e758aba4bcd1b2247900369cbeffbd8275a..b02a4c7e54b538c0192a058caa660c465f09db5f 100644 --- a/lib/compiler_rt/memmove.zig +++ b/lib/compiler_rt/memmove.zig @@ -14,7 +14,7 @@ comptime { .visibility = compiler_rt.visibility, }; - if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64) + if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64) @export(&memmoveSmall, export_options) else @export(&memmoveFast, export_options); diff --git a/lib/docs/wasm/markdown/Document.zig b/lib/docs/wasm/markdown/Document.zig index 97507506af7a15bb5a800085930709d1446d8a11..7cde78f32b5ca948ab6e940f558a43dcd9d9bacc 100644 --- a/lib/docs/wasm/markdown/Document.zig +++ b/lib/docs/wasm/markdown/Document.zig @@ -108,7 +108,7 @@ pub const Node = struct { // In Debug and ReleaseSafe builds, there may be hidden extra fields // included for safety checks. Without such safety checks enabled, // we always want this union to be 8 bytes. - if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { + if (builtin.mode != .debug and builtin.mode != .safe) { assert(@sizeOf(Data) == 8); } } diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig index 65f677fb4e95b301403ef95f3f7f4034697df856..a6e1a65fbb6fcaba7313cea9503bfd06cc2fd4de 100644 --- a/lib/fuzzer.zig +++ b/lib/fuzzer.zig @@ -41,8 +41,8 @@ fn logOverride( var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); const gpa = switch (builtin.mode) { - .Debug, .ReleaseSafe => safe_allocator.allocator(), - .ReleaseFast, .ReleaseSmall => std.heap.smp_allocator, + .debug, .safe => safe_allocator.allocator(), + .fast, .small => std.heap.smp_allocator, }; // Seperate from `exec` to allow initialization before `exec` is. @@ -1209,7 +1209,7 @@ const Fuzzer = struct { f.req_bytes = @intCast(f.input_builder.bytes_table.items.len); const quality: Input.Best.Quality = .{ .n_pcs = n_pcs: { - @setRuntimeSafety(builtin.mode == .Debug); // Necessary for vectorization + @setRuntimeSafety(builtin.mode == .debug); // Necessary for vectorization var n: u32 = 0; for (exec.pc_counters) |c| { n += @intFromBool(c != 0); diff --git a/lib/std/Build.zig b/lib/std/Build.zig index fc2d9909729f1417a4ac486ffea254846137d09b..79b681e7404623d141293d7379d88c94f196f683 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -1210,13 +1210,16 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw return null; }, .scalar => |s| { - if (std.meta.stringToEnum(T, s)) |enum_lit| { - return enum_lit; - } else { - log.err("expected -D{s} to be of type {s}", .{ name, @typeName(T) }); - b.markInvalidUserInput(); - return null; + if (T == std.lang.Optimize) { + if (std.lang.Optimize.fromString(s)) |tag| { + return tag; + } + } else if (std.meta.stringToEnum(T, s)) |tag| { + return tag; } + log.err("expected -D{s} to be of type {q}", .{ name, @typeName(T) }); + b.markInvalidUserInput(); + return null; }, }, .string => switch (option_ptr.value) { @@ -1262,23 +1265,36 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, .scalar => |s| { const Child = @typeInfo(T).pointer.child; - const value = std.meta.stringToEnum(Child, s) orelse { - log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) }); - b.markInvalidUserInput(); - return null; - }; - return arena.dupe(Child, &[_]Child{value}) catch @panic("OOM"); + if (Child == std.lang.Optimize) { + if (std.lang.Optimize.fromString(s)) |tag| { + return arena.dupe(Child, &.{tag}) catch @panic("OOM"); + } + } else { + if (std.meta.stringToEnum(Child, s)) |tag| { + return arena.dupe(Child, &.{tag}) catch @panic("OOM"); + } + } + log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) }); + b.markInvalidUserInput(); + return null; }, .list => |lst| { const Child = @typeInfo(T).pointer.child; const new_list = graph.alloc(Child, lst.items.len); for (new_list, lst.items) |*new_item, str| { - new_item.* = std.meta.stringToEnum(Child, str) orelse { - log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) }); - b.markInvalidUserInput(); - arena.free(new_list); - return null; - }; + if (Child == std.lang.Optimize) { + if (std.lang.Optimize.fromString(str)) |tag| { + new_item.* = tag; + continue; + } + } + if (std.meta.stringToEnum(Child, str)) |tag| { + new_item.* = tag; + continue; + } + log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) }); + b.markInvalidUserInput(); + return null; } return new_list; }, @@ -1359,14 +1375,14 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions) } return switch (graph.release_mode) { - .off => .Debug, + .off => .debug, .any => { std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{}); process.exit(1); }, - .fast => .ReleaseFast, - .safe => .ReleaseSafe, - .small => .ReleaseSmall, + .fast => .fast, + .safe => .safe, + .small => .small, }; } diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig index b839523867b4f151b9761b7178bd2d0290e593eb..31da18abfd88368efb7ded2112d3343bdcf6201a 100644 --- a/lib/std/Build/Configuration.zig +++ b/lib/std/Build/Configuration.zig @@ -1655,10 +1655,10 @@ pub const Module = struct { pub fn init(o: ?std.builtin.OptimizeMode) Optimize { return switch (o orelse return .default) { - .Debug => .debug, - .ReleaseSafe => .safe, - .ReleaseFast => .fast, - .ReleaseSmall => .small, + .debug => .debug, + .safe => .safe, + .fast => .fast, + .small => .small, }; } }; diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index cc0ac4e99d52b94973fd6bc5269790deff2898cf..b14e0c254846d0bda46e06f735015f877dcf9a36 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -390,7 +390,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { @tagName(options.kind) else owner.fmt("{t} {s}", .{ options.kind, name }), - @tagName(options.root_module.optimize orelse .Debug), + @tagName(options.root_module.optimize orelse .debug), resolved_target.query.zigTriple(arena) catch @panic("OOM"), }); @@ -645,7 +645,7 @@ pub fn producesPdbFile(compile: *Compile) bool { if (target.ofmt == .c) return false; if (compile.use_llvm == false) return false; if (compile.root_module.strip == true or - (compile.root_module.strip == null and compile.root_module.optimize == .ReleaseSmall)) + (compile.root_module.strip == null and compile.root_module.optimize == .small)) { return false; } diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig index 438ee0d31b4bb907690c3f355a16d10392b1b60f..4f58bc8bdf7645ae97bd1131a13974552d07e7a8 100644 --- a/lib/std/Io/Dispatch.zig +++ b/lib/std/Io/Dispatch.zig @@ -3897,7 +3897,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { if (memory.len == 0) return; switch (c.errno(c.munmap(memory.ptr, memory.len))) { .SUCCESS => {}, - else => |err| if (builtin.mode == .Debug) + else => |err| if (builtin.mode == .debug) std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }), } mm.* = undefined; diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index b3cc49cd3f792f3a3c70e086d9c9bf2034abc56c..d1ba12a8e29f0b9c38915cacbe04514303cc06dc 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -4,7 +4,7 @@ const builtin = @import("builtin"); const native_os = builtin.os.tag; const is_windows = native_os == .windows; const is_darwin = native_os.isDarwin(); -const is_debug = builtin.mode == .Debug; +const is_debug = builtin.mode == .debug; const std = @import("../std.zig"); const Io = std.Io; @@ -440,12 +440,12 @@ pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum { pub const apc_align = @max(default_fn_align, 2); const default_fn_align = switch (builtin.mode) { - .Debug, .ReleaseSafe, .ReleaseFast => switch (builtin.cpu.arch) { + .debug, .safe, .fast => switch (builtin.cpu.arch) { else => |arch| @compileError("Unsupported architecture: " ++ @tagName(arch)), .arm, .thumb => 4, .aarch64, .x86, .x86_64 => 16, }, - .ReleaseSmall => 1, + .small => 1, }; const Runnable = struct { @@ -18172,7 +18172,7 @@ fn fileMemoryMapCreate( error.Unseekable, error.Canceled, error.AccessDenied => |e| return e, error.OperationUnsupported => {}, else => { - if (builtin.mode == .Debug) + if (builtin.mode == .debug) std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err}); }, } @@ -18279,7 +18279,7 @@ fn createFileMap( .INVALID_VIEW_SIZE => |status| return windows.statusBug(status), else => |status| return windows.unexpectedStatus(status), } - if (builtin.mode == .Debug) { + if (builtin.mode == .debug) { const page_size = std.heap.pageSize(); const alignment: Alignment = .fromByteUnits(page_size); assert(contents_len == alignment.forward(len)); @@ -18370,7 +18370,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) { .SUCCESS => {}, else => |e| { - if (builtin.mode == .Debug) + if (builtin.mode == .debug) std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, e }); }, } diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig index c2c7e57edff411b2c469519858391f3d1eb0724d..59d932311384d4e3de96ef51d618e61338e4783c 100644 --- a/lib/std/Io/Uring.zig +++ b/lib/std/Io/Uring.zig @@ -4050,7 +4050,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { if (memory.len == 0) return; switch (linux.errno(linux.munmap(memory.ptr, memory.len))) { .SUCCESS => {}, - else => |err| if (builtin.mode == .Debug) + else => |err| if (builtin.mode == .debug) std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }), } mm.* = undefined; diff --git a/lib/std/Random/benchmark.zig b/lib/std/Random/benchmark.zig index 1e23c933912851a7f539fd17f076b362b73a27ec..59b6c8168045f7e28963e066f54e472e77555f04 100644 --- a/lib/std/Random/benchmark.zig +++ b/lib/std/Random/benchmark.zig @@ -122,7 +122,7 @@ fn usage() void { } fn mode(comptime x: comptime_int) comptime_int { - return if (builtin.mode == .Debug) x / 64 else x; + return if (builtin.mode == .debug) x / 64 else x; } pub fn main(init: std.process.Init) !void { diff --git a/lib/std/c/darwin/dispatch.zig b/lib/std/c/darwin/dispatch.zig index 770eadf7170f915d877d3d079c7d13b9585ae0a1..5a00b856192b64e786daad59cada13eca06b6ec7 100644 --- a/lib/std/c/darwin/dispatch.zig +++ b/lib/std/c/darwin/dispatch.zig @@ -44,8 +44,8 @@ pub const once_t = enum(isize) { once_f(predicate, context, function); } else asm volatile ("" ::: .{ .memory = true }); switch (builtin.mode) { - .Debug, .ReleaseSafe => {}, - .ReleaseFast, .ReleaseSmall => if (predicate.* != .done) unreachable, + .debug, .safe => {}, + .fast, .small => if (predicate.* != .done) unreachable, } } }; diff --git a/lib/std/compress/flate/Compress.zig b/lib/std/compress/flate/Compress.zig index 23ca2cb634a086080d49ddede293691046f13b4c..167bddd1b6923b2dd22fa2267c38c6e5118f8c39 100644 --- a/lib/std/compress/flate/Compress.zig +++ b/lib/std/compress/flate/Compress.zig @@ -738,7 +738,7 @@ fn matchAndAddHash(c: *Compress, i: usize, h: Hash, gt: u16, max_chain: u16, goo fn clenHlen(freqs: [19]u16) u4 { // Note that the first four codes (16, 17, 18, and 0) are always present. - if (builtin.mode != .ReleaseSmall and (std.simd.suggestVectorLength(u16) orelse 1) >= 8) { + if (builtin.mode != .small and (std.simd.suggestVectorLength(u16) orelse 1) >= 8) { const V = @Vector(16, u16); const hlen_mul: V = comptime m: { var hlen_mul: [16]u16 = undefined; diff --git a/lib/std/compress/flate/token.zig b/lib/std/compress/flate/token.zig index 3c0866896d2cd966e3bd23fdd82cecfa54761fc8..de84f045e83d7296a079326a78dc95fc29b04c1b 100644 --- a/lib/std/compress/flate/token.zig +++ b/lib/std/compress/flate/token.zig @@ -57,9 +57,9 @@ const fixed_dist = blk: { }; // All paramters of codes can be derived matchematically, however some are faster to -// do via lookup table. For ReleaseSmall, we do all mathematically to save space. -pub const LenCode = if (builtin.mode != .ReleaseSmall) LookupLenCode else ShortLenCode; -pub const DistCode = if (builtin.mode != .ReleaseSmall) LookupDistCode else ShortDistCode; +// do via lookup table. For -Osmall, we do all mathematically to save space. +pub const LenCode = if (builtin.mode != .small) LookupLenCode else ShortLenCode; +pub const DistCode = if (builtin.mode != .small) LookupDistCode else ShortDistCode; const ShortLenCode = ShortCode(u8, u2, u3, true); const ShortDistCode = ShortCode(u15, u1, u4, false); /// For length and distance codes, they having this format. diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig index d10f92550a5877b7dfde918a2e9718af948569bb..1c707815872a62d57417f04d572d7d6006110aac 100644 --- a/lib/std/crypto/25519/field.zig +++ b/lib/std/crypto/25519/field.zig @@ -7,8 +7,8 @@ const NotSquareError = crypto.errors.NotSquareError; // Inline conditionally, when it can result in large code generation. const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) { - .ReleaseSafe, .ReleaseFast => .@"inline", - .Debug, .ReleaseSmall => .auto, + .safe, .fast => .@"inline", + .debug, .small => .auto, }; pub const Fe = struct { diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index ef19aac818b764604ed562d2d6832170f4ed91f9..2cc49344b39108a118c000506b531e7520d91047 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -493,7 +493,7 @@ fn usage() void { } fn mode(comptime x: comptime_int) comptime_int { - return if (builtin.mode == .Debug) x / 64 else x; + return if (builtin.mode == .debug) x / 64 else x; } pub fn main(init: std.process.Init) !void { diff --git a/lib/std/crypto/ghash_polyval.zig b/lib/std/crypto/ghash_polyval.zig index 9f648c3fb34048f703f0346f96ea543d901a5d94..2ae68da1d654ee0a1ff33390637c5240a3f26aae 100644 --- a/lib/std/crypto/ghash_polyval.zig +++ b/lib/std/crypto/ghash_polyval.zig @@ -30,7 +30,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { pub const mac_length = 16; pub const key_length = 16; - const pc_count = if (builtin.mode != .ReleaseSmall) 16 else 2; + const pc_count = if (builtin.mode != .small) 16 else 2; const agg_4_threshold = 22; const agg_8_threshold = 84; const agg_16_threshold = 328; @@ -61,7 +61,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { hx[0] = h; hx[1] = reduce(clsq128(hx[0])); // h^2 - if (builtin.mode != .ReleaseSmall) { + if (builtin.mode != .small) { hx[2] = reduce(clmul128(hx[1], h)); // h^3 hx[3] = reduce(clsq128(hx[1])); // h^4 = h^2^2 if (block_count >= agg_8_threshold) { @@ -303,7 +303,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { var i: usize = 0; - if (builtin.mode != .ReleaseSmall and msg.len >= agg_16_threshold * block_length) { + if (builtin.mode != .small and msg.len >= agg_16_threshold * block_length) { // 16-blocks aggregated reduction while (i + 256 <= msg.len) : (i += 256) { var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[15 - 0]); @@ -313,7 +313,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { } acc = reduce(u); } - } else if (builtin.mode != .ReleaseSmall and msg.len >= agg_8_threshold * block_length) { + } else if (builtin.mode != .small and msg.len >= agg_8_threshold * block_length) { // 8-blocks aggregated reduction while (i + 128 <= msg.len) : (i += 128) { var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[7 - 0]); @@ -323,7 +323,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { } acc = reduce(u); } - } else if (builtin.mode != .ReleaseSmall and msg.len >= agg_4_threshold * block_length) { + } else if (builtin.mode != .small and msg.len >= agg_4_threshold * block_length) { // 4-blocks aggregated reduction while (i + 64 <= msg.len) : (i += 64) { var u = clmul128(acc ^ mem.readInt(u128, msg[i..][0..16], endian), st.hx[3 - 0]); diff --git a/lib/std/crypto/kangarootwelve.zig b/lib/std/crypto/kangarootwelve.zig index f43ae24c69172b000b2f7d4b420f03f93f505e64..735d476591854adae4ea5a4a417a3ce6d8a67b86 100644 --- a/lib/std/crypto/kangarootwelve.zig +++ b/lib/std/crypto/kangarootwelve.zig @@ -1398,7 +1398,7 @@ test "KT128 sequential and parallel produce same output for many random lengths" var prng = std.Random.DefaultPrng.init(std.testing.random_seed); const random = prng.random(); - const num_tests = if (builtin.mode == .Debug) 10 else 1000; + const num_tests = if (builtin.mode == .debug) 10 else 1000; const max_length = 250000; for (0..num_tests) |_| { diff --git a/lib/std/crypto/keccak_p.zig b/lib/std/crypto/keccak_p.zig index 6aa2345aed5550d1d3a320887a8d99e4d115f277..b707833e2d7a5a56cc8c38cd989ff6bee5a9b0a1 100644 --- a/lib/std/crypto/keccak_p.zig +++ b/lib/std/crypto/keccak_p.zig @@ -202,7 +202,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type // In debug mode, track transitions to prevent insecure ones. const Op = enum { uninitialized, initialized, updated, absorb, squeeze }; - const TransitionTracker = if (mode == .Debug) struct { + const TransitionTracker = if (mode == .debug) struct { op: Op = .uninitialized, fn to(tracker: *@This(), next_op: Op) void { @@ -294,7 +294,7 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type /// Permute the state pub fn permute(self: *Self) void { - if (mode == .Debug) { + if (mode == .debug) { if (self.transition.op == .absorb and self.offset > 0) { @panic("cannot permute with pending input - call fillBlock() or pad() instead"); } diff --git a/lib/std/crypto/pcurves/p256/p256_64.zig b/lib/std/crypto/pcurves/p256/p256_64.zig index e79d51814e28ae67719c50354e4fe1c0a7061697..8cc9016ed38957ae5cd6647141dd0909dc3b90c3 100644 --- a/lib/std/crypto/pcurves/p256/p256_64.zig +++ b/lib/std/crypto/pcurves/p256/p256_64.zig @@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -437,7 +437,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -730,7 +730,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -783,7 +783,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -826,7 +826,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -869,7 +869,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -1022,7 +1022,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1297,7 +1297,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); out1.* = x1; @@ -1315,7 +1315,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -1343,7 +1343,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[3]); const x2 = (arg1[2]); @@ -1452,7 +1452,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[31])) << 56); const x2 = (@as(u64, (arg1[30])) << 48); @@ -1527,7 +1527,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = @as(u64, 0x1); out1[1] = 0xffffffff00000000; @@ -1544,7 +1544,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[5]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xffffffffffffffff; out1[1] = 0xffffffff; @@ -1582,7 +1582,7 @@ pub fn msat(out1: *[5]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1816,7 +1816,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0x67ffffffb8000000; out1[1] = 0xc000000038000000; diff --git a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig index c549831b20e3260874f8c97179394b044b291741..db350196a4ca66f7624a39569b2d7e3296745821 100644 --- a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig +++ b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig @@ -110,7 +110,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -485,7 +485,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -826,7 +826,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -879,7 +879,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -922,7 +922,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -965,7 +965,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -1178,7 +1178,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1501,7 +1501,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); out1.* = x1; @@ -1519,7 +1519,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -1547,7 +1547,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[3]); const x2 = (arg1[2]); @@ -1656,7 +1656,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[31])) << 56); const x2 = (@as(u64, (arg1[30])) << 48); @@ -1731,7 +1731,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xc46353d039cdaaf; out1[1] = 0x4319055258e8617b; @@ -1748,7 +1748,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[5]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xf3b9cac2fc632551; out1[1] = 0xbce6faada7179e84; @@ -1786,7 +1786,7 @@ pub fn msat(out1: *[5]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -2020,7 +2020,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xd739262fb7fcfbb5; out1[1] = 0x8ac6f75d20074414; diff --git a/lib/std/crypto/pcurves/p384/p384_64.zig b/lib/std/crypto/pcurves/p384/p384_64.zig index d6f33028f73e744e048bb764b588bc7379868845..99d9dc82b2ba99d26de4c324c5c3ac239846a47a 100644 --- a/lib/std/crypto/pcurves/p384/p384_64.zig +++ b/lib/std/crypto/pcurves/p384/p384_64.zig @@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -2862,7 +2862,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5])))))); out1.* = x1; @@ -2880,7 +2880,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -2914,7 +2914,7 @@ pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[5]); const x2 = (arg1[4]); @@ -3069,7 +3069,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[47])) << 56); const x2 = (@as(u64, (arg1[46])) << 48); @@ -3176,7 +3176,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xffffffff00000001; out1[1] = 0xffffffff; @@ -3195,7 +3195,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[7]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xffffffff; out1[1] = 0xffffffff00000000; @@ -3235,7 +3235,7 @@ pub fn msat(out1: *[7]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[6]u64, arg1: u64, arg2: [7]u64, arg3: [7]u64, arg4: [6]u64, arg5: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -3561,7 +3561,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xfff69400fff18fff; out1[1] = 0x2b7feffffd3ff; diff --git a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig index 74f7e7813fed2a5bc0c685d5f9ba85e478ed3ce0..0b618e615442dfccd128b264029302205c286ecd 100644 --- a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig +++ b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig @@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -2916,7 +2916,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5])))))); out1.* = x1; @@ -2934,7 +2934,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -2968,7 +2968,7 @@ pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[5]); const x2 = (arg1[4]); @@ -3123,7 +3123,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[47])) << 56); const x2 = (@as(u64, (arg1[46])) << 48); @@ -3230,7 +3230,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0x1313e695333ad68d; out1[1] = 0xa7e5f24db74f5885; @@ -3249,7 +3249,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[7]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xecec196accc52973; out1[1] = 0x581a0db248b0a77a; @@ -3289,7 +3289,7 @@ pub fn msat(out1: *[7]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[6]u64, arg1: u64, arg2: [7]u64, arg3: [7]u64, arg4: [6]u64, arg5: [6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -3615,7 +3615,7 @@ pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[6]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0x49589ae0e6045b6a; out1[1] = 0x3c9a5352870040ed; diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig index 547da19bea45f80db08cd2bc1d5172265cecd72a..8decda2f2525f288583ced40b12c7413862ebf6d 100644 --- a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig @@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1430,7 +1430,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); out1.* = x1; @@ -1448,7 +1448,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -1476,7 +1476,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[3]); const x2 = (arg1[2]); @@ -1585,7 +1585,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[31])) << 56); const x2 = (@as(u64, (arg1[30])) << 48); @@ -1660,7 +1660,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0x1000003d1; out1[1] = 0x0; @@ -1677,7 +1677,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[5]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xfffffffefffffc2f; out1[1] = 0xffffffffffffffff; @@ -1715,7 +1715,7 @@ pub fn msat(out1: *[5]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -1949,7 +1949,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xf201a41831525e0a; out1[1] = 0x9953f9ddcd648d85; diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig index 71e6f1baba7bd6107d85097e2ce297402f4a475a..09bfc15a10d44970b38d7f51b802a28cb908afe5 100644 --- a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig @@ -79,7 +79,7 @@ fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { /// out1: [0x0 ~> 0xffffffffffffffff] /// out2: [0x0 ~> 0xffffffffffffffff] fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x = @as(u128, arg1) * @as(u128, arg2); out1.* = @as(u64, @truncate(x)); @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const mask = 0 -% @as(u64, arg1); out1.* = (mask & arg3) | ((~mask) & arg2); @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { /// 0 ≤ eval out1 < m /// pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl /// 0 ≤ eval out1 < m /// pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme /// 0 ≤ eval out1 < m /// pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[0]); var x2: u64 = undefined; @@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo /// 0 ≤ eval out1 < m /// pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[1]); const x2 = (arg1[2]); @@ -1490,7 +1490,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma /// Output Bounds: /// out1: [0x0 ~> 0xffffffffffffffff] pub fn nonzero(out1: *u64, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); out1.* = x1; @@ -1508,7 +1508,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); @@ -1536,7 +1536,7 @@ pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (arg1[3]); const x2 = (arg1[2]); @@ -1645,7 +1645,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); const x1 = (@as(u64, (arg1[31])) << 56); const x2 = (@as(u64, (arg1[30])) << 48); @@ -1720,7 +1720,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { /// 0 ≤ eval out1 < m /// pub fn setOne(out1: *MontgomeryDomainFieldElement) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0x402da1732fc9bebf; out1[1] = 0x4551231950b75fc4; @@ -1737,7 +1737,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn msat(out1: *[5]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xbfd25e8cd0364141; out1[1] = 0xbaaedce6af48a03b; @@ -1775,7 +1775,7 @@ pub fn msat(out1: *[5]u64) void { /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); var x1: u64 = undefined; var x2: u1 = undefined; @@ -2009,7 +2009,7 @@ pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[ /// Output Bounds: /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] pub fn divstepPrecomp(out1: *[4]u64) void { - @setRuntimeSafety(mode == .Debug); + @setRuntimeSafety(mode == .debug); out1[0] = 0xd7431a4d2b9cb4e9; out1[1] = 0xab67d35a32d9c503; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 9a83de8e1061d603b3e82c80d6e84cc8a640441b..8aaee0e29edaba4523a70710de7eca31cf0bc078 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -241,8 +241,8 @@ pub const Symbol = struct { /// library, when the caller probably wants to use the optimization mode of /// their own module. pub const runtime_safety = switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; /// Whether we can unwind the stack on this target, allowing capturing and/or printing the current @@ -257,7 +257,7 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) { // because Emscripten's implementation is very slow. .wasm32, .wasm64, - => native_os == .emscripten and builtin.mode == .Debug, + => native_os == .emscripten and builtin.mode == .debug, // `@returnAddress()` is unsupported in LLVM 21. .bpfel, @@ -419,16 +419,16 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con /// Invokes detectable illegal behavior when `ok` is `false`. /// -/// In Debug and ReleaseSafe modes, calls to this function are always +/// In debug and safe modes, calls to this function are always /// generated, and the `unreachable` statement triggers a panic. /// -/// In ReleaseFast and ReleaseSmall modes, calls to this function are optimized +/// In fast and small modes, calls to this function are optimized /// away, and in fact the optimizer is able to use the assertion in its /// heuristics. /// /// Inside a test block, it is best to use the `testing` module rather than /// this function, because this function may not detect a test failure in -/// ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert +/// fast and small mode. Outside of a test block, this assert /// function is the correct function to use. pub fn assert(ok: bool) void { @disableInstrumentation(); @@ -1760,7 +1760,7 @@ test "manage resources correctly" { /// In release mode, it is size 0 and all methods are no-ops. /// This is a pre-made type with default settings. /// For more advanced usage, see `ConfigurableTrace`. -pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug); +pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .debug); pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime is_enabled: bool) type { return struct { diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 92e04955ed48a2628f78ae040326c3a853f88b11..7cdc44269cdc95b492eb8ac718a53d7fe721af55 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -261,7 +261,7 @@ test printInt { /// Converts values in the range [0, 100) to a base 10 string. pub fn digits2(value: u8) [2]u8 { - if (builtin.mode == .ReleaseSmall) { + if (builtin.mode == .small) { return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) }; } else { return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*; @@ -924,7 +924,7 @@ test "enum" { // test very large enum to verify ct branch quota is large enough // TODO: https://github.com/ziglang/zig/issues/15609 - if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) { + if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .debug)) { try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); } diff --git a/lib/std/fmt/float.zig b/lib/std/fmt/float.zig index 44a71f90f42c47b608d6db65b1b7a59243680507..25bf97f22ae52df136be9dbbdeab2e0fdedfdc18 100644 --- a/lib/std/fmt/float.zig +++ b/lib/std/fmt/float.zig @@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 { const DT = if (@bitSizeOf(T) <= 64) u64 else u128; const tables = switch (DT) { - u64 => if (@import("builtin").mode == .ReleaseSmall) &Backend64_TablesSmall else &Backend64_TablesFull, + u64 => if (@import("builtin").mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, u128 => &Backend128_Tables, else => unreachable, }; diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index 3f5b763d9b0f2eb207b597c8e41098f272a090d0..a4ea82d68e6fef34b7ade95fe69bffac17e43021 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -355,7 +355,7 @@ fn usage() void { } fn mode(comptime x: comptime_int) comptime_int { - return if (builtin.mode == .Debug) x / 64 else x; + return if (builtin.mode == .debug) x / 64 else x; } pub fn main(init: std.process.Init) !void { diff --git a/lib/std/heap/SafeAllocator.zig b/lib/std/heap/SafeAllocator.zig index cfe24f4c0b1f0dabeaedaff76cc33d6ae32669c3..41199df8aa39d526938dc72a2ceccd80168c3dc0 100644 --- a/lib/std/heap/SafeAllocator.zig +++ b/lib/std/heap/SafeAllocator.zig @@ -39,7 +39,7 @@ const SafeAllocator = @This(); const scoped_log = std.log.scoped(.SafeAllocator); pub const Options = struct { - const is_debug = @import("builtin").mode == .Debug; + const is_debug = @import("builtin").mode == .debug; const page_size_log2 = @max(math.log2_int(usize, std.heap.page_size_max), 8); stack_trace_frames: usize = if (is_debug and std.debug.sys_can_stack_trace) 7 else 0, diff --git a/lib/std/http/test.zig b/lib/std/http/test.zig index 4182a766c5a132f8dca6fa24adafae86ba15e4d2..39f2063f65d7c1b175ce0750e9512abaee3f2c20 100644 --- a/lib/std/http/test.zig +++ b/lib/std/http/test.zig @@ -34,7 +34,7 @@ test "content length reader state update" { } test "trailers" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -121,7 +121,7 @@ test "trailers" { } test "HTTP server handles a chunked transfer coding request" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -190,7 +190,7 @@ test "HTTP server handles a chunked transfer coding request" { } test "echo content server" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -281,7 +281,7 @@ test "echo content server" { } test "Server.Request.respondStreaming non-chunked, unknown content-length" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -360,7 +360,7 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { } test "receiving arbitrary http headers from the client" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -426,7 +426,7 @@ test "receiving arbitrary http headers from the client" { } test "general client/server API coverage" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -922,7 +922,7 @@ test "general client/server API coverage" { } test "Server streams both reading and writing" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1192,7 +1192,7 @@ fn createTestServer(io: Io, S: type) !*TestServer { } test "redirect to different connection" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1280,7 +1280,7 @@ test "redirect to different connection" { } test "boot failed connections from the pool" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 + if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; diff --git a/lib/std/json/Stringify.zig b/lib/std/json/Stringify.zig index 565c41b5e8e96c5bc3d3726df0171554fc8ed4d9..03c5d8fe4611dce85280df2de435194bf9a9fb1f 100644 --- a/lib/std/json/Stringify.zig +++ b/lib/std/json/Stringify.zig @@ -54,8 +54,8 @@ else void = if (build_mode_has_safety) .none else {}, const build_mode_has_safety = switch (@import("builtin").mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; /// The `safety_checks_hint` parameter determines how much memory is used to enable assertions that the above grammar is being followed, @@ -66,7 +66,7 @@ const build_mode_has_safety = switch (@import("builtin").mode) { /// If `.checked_to_fixed_depth` is used, there is additionally an assertion that the nesting depth never exceeds the given limit. /// `.checked_to_fixed_depth` embeds the storage required in the `Stringify` struct. /// `.assumed_correct` requires no space and performs none of these assertions. -/// In `ReleaseFast` and `ReleaseSmall` mode, the given `safety_checks_hint` is ignored and is always treated as `.assumed_correct`. +/// In fast and small optimization modes, the given `safety_checks_hint` is ignored and is always treated as `.assumed_correct`. const safety_checks_hint: union(enum) { /// Rounded up to the nearest multiple of 8. checked_to_fixed_depth: usize, diff --git a/lib/std/lang.zig b/lib/std/lang.zig index 02a1c90e5a915a26a7186d3733a2893a99c765dd..daa2482eec7429bcd90a83ae2e2515681be29187 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -107,13 +107,43 @@ pub const CodeModel = enum(u4) { tiny, }; +/// Deprecated, to be removed after 0.18.0 +pub const OptimizeMode = Optimize; + /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. -pub const OptimizeMode = enum { - Debug, - ReleaseSafe, - ReleaseFast, - ReleaseSmall, +pub const Optimize = enum { + /// Safety checks enabled. Optimize for bug detection, accurate debug info, + /// and compilation speed (in that order). + debug, + /// Safety checks enabled. Optimize for runtime performance. + safe, + /// Safety checks disabled. Optimize for runtime performance. + fast, + /// Safety checks disabled. Optimize for machine code size, then runtime performance. + small, + + /// Deprecated, to be removed after 0.18.0 + pub const Debug: @This() = .debug; + /// Deprecated, to be removed after 0.18.0 + pub const ReleaseSafe: @This() = .safe; + /// Deprecated, to be removed after 0.18.0 + pub const ReleaseFast: @This() = .fast; + /// Deprecated, to be removed after 0.18.0 + pub const ReleaseSmall: @This() = .small; + /// Deprecated, to be removed after 0.18.0 + pub fn fromString(s: []const u8) ?@This() { + return std.StaticStringMap(@This()).initComptime(&.{ + .{ "Debug", .debug }, + .{ "ReleaseSafe", .safe }, + .{ "ReleaseFast", .fast }, + .{ "ReleaseSmall", .small }, + .{ "debug", .debug }, + .{ "safe", .safe }, + .{ "fast", .fast }, + .{ "small", .small }, + }).get(s); + } }; /// The calling convention of a function defines how arguments and return values are passed, as well diff --git a/lib/std/log.zig b/lib/std/log.zig index 5a219a005a6d4274c0d7df0aa16a5cf8ce10f653..9599308b91784eaa0319f1563746de3097405f03 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -53,7 +53,7 @@ pub const Level = enum { /// The default log level is based on build mode. pub const default_level: Level = switch (builtin.mode) { .Debug => .debug, - .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .info, + .safe, .fast, .small => .info, }; pub const ScopeLevel = struct { diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig index f661e56d4ce9e46d51cce9487e783c4df78bed9c..ef3fc97af3d3ea21b7cb525c616d248ffc20da7d 100644 --- a/lib/std/math/hypot.zig +++ b/lib/std/math/hypot.zig @@ -93,13 +93,13 @@ const hypot_test_cases = .{ }; test hypot { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 try expect(hypot(0.3, 0.4) == 0.5); } test "hypot.correct" { if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 inline for (.{ f16, f32, f64, f128 }) |T| { inline for (hypot_test_cases) |v| { @@ -111,7 +111,7 @@ test "hypot.correct" { test "hypot.precise" { if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp inline for (hypot_test_cases) |v| { @@ -122,7 +122,7 @@ test "hypot.precise" { } test "hypot.special" { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 + if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 @setEvalBranchQuota(2000); inline for (.{ f16, f32, f64, f128 }) |T| { try expect(math.isNan(hypot(nan(T), 0.0))); diff --git a/lib/std/process.zig b/lib/std/process.zig index e134ef16d9adb9abed54448861c72b12bb12a4c0..33adef9e29fa5444df291db23aec45045b65d4e2 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -644,7 +644,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 { /// leaks can be accurate. In release builds, this calls `exit` with code zero, /// and does not return. pub fn cleanExit(io: Io) void { - if (builtin.mode == .Debug) return; + if (builtin.mode == .debug) return; _ = io.lockStderr(&.{}, .no_color) catch {}; exit(0); } @@ -809,7 +809,7 @@ pub fn abort() noreturn { // even when linking libc on Windows we use our own abort implementation. // See https://github.com/ziglang/zig/issues/2071 for more details. if (native_os == .windows) { - if (builtin.mode == .Debug and windows.peb().BeingDebugged.toBool()) { + if (builtin.mode == .debug and windows.peb().BeingDebugged.toBool()) { @breakpoint(); } windows.ntdll.RtlExitUserProcess(3); diff --git a/lib/std/sort/block.zig b/lib/std/sort/block.zig index 4c94fb78adb6fde1582e0e806f84cfdfe88ec7a6..674e785afadf9c29f8869044de85bdc3fdfb7c85 100644 --- a/lib/std/sort/block.zig +++ b/lib/std/sort/block.zig @@ -103,7 +103,7 @@ pub fn block( context: anytype, comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool, ) void { - const lessThan = if (builtin.mode == .Debug) struct { + const lessThan = if (builtin.mode == .debug) struct { fn lessThan(ctx: @TypeOf(context), lhs: T, rhs: T) bool { const lt = lessThanFn(ctx, lhs, rhs); const gt = lessThanFn(ctx, rhs, lhs); diff --git a/lib/std/start.zig b/lib/std/start.zig index c95e36e7778e5e6f041d7b51411d1a1e3b353601..2530b80d360c4e9b61bb8f2d4e25006d20aea2c3 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -742,8 +742,8 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; const use_safe_allocator = !is_wasm and switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal. + .debug, .safe => true, + .fast, .small => !builtin.link_libc and builtin.single_threaded, // Also not ideal. }; var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); diff --git a/lib/std/std.zig b/lib/std/std.zig index e7c50a946091a47dccf4cf1301d2982189ff8589..d1d8361967220fe75485de92ef207dfdac3363a0 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -162,7 +162,7 @@ pub const Options = struct { /// This enables `std.http.Client` to log ssl secrets to the file specified by the SSLKEYLOGFILE /// env var. Creating such a log file allows other programs with access to that file to decrypt /// all `std.http.Client` traffic made by this program. - http_enable_ssl_key_log_file: bool = @import("builtin").mode == .Debug, + http_enable_ssl_key_log_file: bool = @import("builtin").mode == .debug, side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations, @@ -192,7 +192,7 @@ pub const Options = struct { /// If this happens the fix is to add the error code to the corresponding /// switch expression, possibly introduce a new error in the error set, and /// send a patch to Zig. - unexpected_error_tracing: bool = @import("builtin").mode == .Debug and switch (@import("builtin").zig_backend) { + unexpected_error_tracing: bool = @import("builtin").mode == .debug and switch (@import("builtin").zig_backend) { .stage2_llvm, .stage2_x86_64 => true, else => false, }, diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index bce7bd281ef314870fe68528cde51d4813a41a17..1ec523e8694eb854692a94fbe560e25b11046a34 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2522,7 +2522,7 @@ pub const Inst = struct { // bigger than expected. Note that in Debug builds, Zig is allowed // to insert a secret field for safety checks. comptime { - if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { + if (builtin.mode != .debug and builtin.mode != .safe) { assert(@sizeOf(Data) == 8); } } diff --git a/src/Builtin.zig b/src/Builtin.zig index 7975f2b04bf7c1ca82c3dc786221f903be884cc4..e70252e47d8427eecac589c9d5711d9286d6b878 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -7,7 +7,7 @@ is_test: bool, single_threaded: bool, link_libc: bool, link_libcpp: bool, -optimize_mode: std.lang.OptimizeMode, +optimize_mode: std.lang.Optimize, error_tracing: bool, valgrind: bool, sanitize_thread: bool, @@ -239,7 +239,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro try buffer.print( \\pub const object_format: std.Target.ObjectFormat = .{f}; - \\pub const mode: std.lang.OptimizeMode = .{f}; + \\/// Deprecated, to be removed after 0.18.0 + \\pub const mode = optimize; + \\pub const optimize: std.lang.Optimize = .{f}; \\pub const link_libc = {}; \\pub const link_libcpp = {}; \\pub const have_error_return_tracing = {}; diff --git a/src/Compilation.zig b/src/Compilation.zig index 293b553d233ce437470ab229ad14c721e33ef56b..83b0f7ff2b206b23c947437fc514ca1c1cefed6a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -172,7 +172,7 @@ verbose_link: bool, link_depfile: ?[]const u8, disable_c_depfile: bool, stack_report: bool, -debug_compiler_runtime_libs: ?std.lang.OptimizeMode, +debug_compiler_runtime_libs: ?std.lang.Optimize, debug_compile_errors: bool, /// Do not check this field directly. Instead, use the `debugIncremental` wrapper function. debug_incremental: bool, @@ -1506,7 +1506,7 @@ pub const CreateOptions = struct { verbose_llvm_bc: ?[]const u8 = null, link_depfile: ?[]const u8 = null, verbose_llvm_cpu_features: bool = false, - debug_compiler_runtime_libs: ?std.lang.OptimizeMode = null, + debug_compiler_runtime_libs: ?std.lang.Optimize = null, debug_compile_errors: bool = false, debug_incremental: bool = false, /// Normally when you create a `Compilation`, Zig will automatically build @@ -2160,7 +2160,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .framework_dirs = options.framework_dirs, .rpath_list = options.rpath_list, .symbol_wrap_set = options.symbol_wrap_set, - .repro = options.linker_repro orelse (options.root_mod.optimize_mode != .Debug), + .repro = options.linker_repro orelse (options.root_mod.optimize_mode != .debug), .allow_shlib_undefined = options.linker_allow_shlib_undefined, .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, .compress_debug_sections = options.linker_compress_debug_sections orelse .none, @@ -3189,8 +3189,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error break :p try p.toStringZ(arena); }, - .is_debug = comp.root_mod.optimize_mode == .Debug, - .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, + .is_debug = comp.root_mod.optimize_mode == .debug, + .is_small = comp.root_mod.optimize_mode == .small, .time_report = if (comp.time_report) |*p| p else null, .sanitize_thread = comp.config.any_sanitize_thread, .fuzz = comp.config.any_fuzz, @@ -4744,7 +4744,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const optimize_mode = std.lang.OptimizeMode.ReleaseSmall; + const optimize_mode: std.lang.Optimize = .small; const output_mode = std.lang.OutputMode.Exe; const resolved_target: Module.ResolvedTarget = .{ .result = std.zig.system.resolveTargetQuery(io, .{ @@ -5910,8 +5910,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // them being defined matches the behavior of how MSVC calls rc.exe which is the more // relevant behavior in this case. switch (rc_src.owner.optimize_mode) { - .Debug, .ReleaseSafe => {}, - .ReleaseFast, .ReleaseSmall => try argv.append("-DNDEBUG"), + .debug, .safe => {}, + .fast, .small => try argv.append("-DNDEBUG"), } try argv.appendSlice(rc_src.extra_flags); try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path }); @@ -6178,11 +6178,11 @@ fn addCommonCCArgs( // LLVM IR files don't support these flags. if (ext != .ll and ext != .bc) { switch (mod.optimize_mode) { - .Debug => {}, - .ReleaseSafe => { + .debug => {}, + .safe => { try argv.append("-D_FORTIFY_SOURCE=2"); }, - .ReleaseFast, .ReleaseSmall => { + .fast, .small => { try argv.append("-DNDEBUG"); }, } @@ -6333,7 +6333,7 @@ fn addCommonCCArgs( } } - if (mod.optimize_mode != .Debug) { + if (mod.optimize_mode != .debug) { try argv.append("-Werror=date-time"); } }, @@ -6412,18 +6412,18 @@ fn addCommonCCArgs( } switch (mod.optimize_mode) { - .Debug => { + .debug => { // Clang has -Og for compatibility with GCC, but currently it is just equivalent // to -O1. Besides potentially impairing debugging, -O1/-Og significantly // increases compile times. try argv.append("-O0"); }, - .ReleaseSafe => { + .safe => { // See the comment in the BuildModeFastRelease case for why we pass -O2 rather // than -O3 here. try argv.append("-O2"); }, - .ReleaseFast => { + .fast => { // Here we pass -O2 rather than -O3 because, although we do the equivalent of // -O3 in Zig code, the justification for the difference here is that Zig // has better detection and prevention of undefined behavior, so -O3 is safer for @@ -6431,7 +6431,7 @@ fn addCommonCCArgs( // running in -O2 and thus the -O3 path has been tested less. try argv.append("-O2"); }, - .ReleaseSmall => { + .small => { try argv.append("-Os"); }, } @@ -7557,15 +7557,15 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { /// This decides the optimization mode for all zig-provided libraries, including /// compiler-rt, libcxx, libc, libunwind, etc. -pub fn compilerRtOptMode(comp: Compilation) std.lang.OptimizeMode { +pub fn compilerRtOptMode(comp: Compilation) std.lang.Optimize { if (comp.debug_compiler_runtime_libs) |mode| { return mode; } const target = &comp.root_mod.resolved_target.result; switch (comp.root_mod.optimize_mode) { - .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(target), - .ReleaseFast => return .ReleaseFast, - .ReleaseSmall => return .ReleaseSmall, + .debug, .safe => return target_util.defaultCompilerRtOptimizeMode(target), + .fast => return .fast, + .small => return .small, } } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index ad0d709425cfaccd284cd929bc7329604a325213..85915ded1b97d4e324a1cebbdb1385758ebea6f0 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -59,7 +59,7 @@ export_memory: bool, shared_memory: bool, is_test: bool, debug_format: DebugFormat, -root_optimize_mode: std.lang.OptimizeMode, +root_optimize_mode: std.lang.Optimize, root_strip: bool, root_error_tracing: bool, dll_export_fns: bool, @@ -80,7 +80,7 @@ pub const Options = struct { is_test: bool, have_zcu: bool, emit_bin: bool, - root_optimize_mode: ?std.lang.OptimizeMode = null, + root_optimize_mode: ?std.lang.Optimize = null, root_strip: ?bool = null, root_error_tracing: ?bool = null, link_mode: ?std.lang.LinkMode = null, @@ -196,7 +196,7 @@ pub fn resolve(options: Options) ResolveError!Config { break :b options.use_lib_llvm orelse true; }; - const root_optimize_mode = options.root_optimize_mode orelse .Debug; + const root_optimize_mode = options.root_optimize_mode orelse .debug; // Make a decision on whether to use Clang or Aro for translate-c and compiling C files. const c_frontend: CFrontend = b: { @@ -357,7 +357,7 @@ pub fn resolve(options: Options) ResolveError!Config { if (!use_lib_llvm and options.emit_bin) break :b false; // Prefer LLVM for release builds. - if (root_optimize_mode != .Debug) break :b true; + if (root_optimize_mode != .debug) break :b true; // load_dynamic_library standalone test not passing on this combination // https://github.com/ziglang/zig/issues/24080 @@ -486,7 +486,7 @@ pub fn resolve(options: Options) ResolveError!Config { const root_strip = b: { if (options.root_strip) |x| break :b x; - if (root_optimize_mode == .ReleaseSmall) break :b true; + if (root_optimize_mode == .small) break :b true; if (!target_util.hasDebugInfo(target)) break :b true; break :b false; }; @@ -512,8 +512,8 @@ pub fn resolve(options: Options) ResolveError!Config { if (root_strip) break :b false; if (!backend_supports_error_tracing) break :b false; break :b switch (root_optimize_mode) { - .Debug => true, - .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, + .debug => true, + .safe, .fast, .small => false, }; }; diff --git a/src/Module.zig b/src/Module.zig index c351d9eaf4bb29baa41306fa0b80cf3f42276e08..d245c0cf02f15bb7ed695dcac2914285c9debfb6 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -26,7 +26,7 @@ fully_qualified_name: []const u8, deps: Deps = .{}, resolved_target: ResolvedTarget, -optimize_mode: std.lang.OptimizeMode, +optimize_mode: std.lang.Optimize, code_model: std.lang.CodeModel, single_threaded: bool, error_tracing: bool, @@ -67,7 +67,7 @@ pub const CreateOptions = struct { pub const Inherited = struct { /// If this is null then `parent` must be non-null. resolved_target: ?ResolvedTarget = null, - optimize_mode: ?std.lang.OptimizeMode = null, + optimize_mode: ?std.lang.Optimize = null, code_model: ?std.lang.CodeModel = null, single_threaded: ?bool = null, error_tracing: ?bool = null, @@ -144,7 +144,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { if (options.inherited.valgrind) |x| break :b x; if (options.parent) |p| break :b p.valgrind; if (strip) break :b false; - break :b optimize_mode == .Debug; + break :b optimize_mode == .debug; }; const single_threaded = b: { @@ -212,7 +212,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { const omit_frame_pointer = b: { if (options.inherited.omit_frame_pointer) |x| break :b x; if (options.parent) |p| break :b p.omit_frame_pointer; - if (optimize_mode == .ReleaseSmall) { + if (optimize_mode == .small) { // On x86, in most cases, keeping the frame pointer usually results in smaller binary size. // This has to do with how instructions for memory access via the stack base pointer register (when keeping the frame pointer) // are smaller than instructions for memory access via the stack pointer register (when omitting the frame pointer). @@ -251,21 +251,21 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { }; const is_safe_mode = switch (optimize_mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; const sanitize_c: std.zig.SanitizeC = b: { if (options.inherited.sanitize_c) |x| break :b x; if (options.parent) |p| break :b p.sanitize_c; break :b switch (optimize_mode) { - .Debug => .full, + .debug => .full, // It's recommended to use the minimal runtime in production // environments due to the security implications of the full runtime. // The minimal runtime doesn't provide much benefit over simply // trapping, however, so we do that instead. - .ReleaseSafe => .trap, - .ReleaseFast, .ReleaseSmall => .off, + .safe => .trap, + .fast, .small => .off, }; }; diff --git a/src/Sema.zig b/src/Sema.zig index 20df87823ce2703925d26d0f5e7020415b00d7ce..6dafdeb0ee6c53fb6f116272e28c641239573cff 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -532,20 +532,20 @@ pub const Block = struct { fn wantSafeTypes(block: *const Block) bool { return block.want_safety orelse switch (block.ownerModule().optimize_mode) { - .Debug => true, - .ReleaseSafe => true, - .ReleaseFast => false, - .ReleaseSmall => false, + .debug => true, + .safe => true, + .fast => false, + .small => false, }; } fn wantSafety(block: *const Block) bool { if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks return block.want_safety orelse switch (block.ownerModule().optimize_mode) { - .Debug => true, - .ReleaseSafe => true, - .ReleaseFast => false, - .ReleaseSmall => false, + .debug => true, + .safe => true, + .fast => false, + .small => false, }; } @@ -2247,7 +2247,7 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { .inferred_alloc_comptime => unreachable, // assertion failure else => {}, } - // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so + // LLVM fails to eliminate this `classify` call in -Ofast, which hurts performance, so // we must explicitly check for `std.debug.runtime_safety`. if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { .no_possible_value => unreachable, // values of this type do not exist diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig index 7b976acde1c5401ef294ede213416828c55d26a9..ad40e86902d4273b2b558fa1b1b97add12b29345 100644 --- a/src/codegen/aarch64/Mir.zig +++ b/src/codegen/aarch64/Mir.zig @@ -70,8 +70,8 @@ pub fn emit( const func_align = switch (nav.resolved.?.@"align") { .none => switch (mod.optimize_mode) { - .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => target_util.minFunctionAlignment(target), + .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), + .small => target_util.minFunctionAlignment(target), }, else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), }; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 0dc4ae6f3997ae55f4b068f725d5a02b3dea50a7..9ecd3a4e0b1f4483c878e056cf3786bccafed62b 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -453,8 +453,8 @@ pub const Function = struct { fn wantSafety(f: *Function) bool { return switch (f.dg.mod.optimize_mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; } @@ -1306,8 +1306,8 @@ pub const DeclGen = struct { }; const safety_on = switch (dg.mod.optimize_mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }; switch (ty.toIntern()) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index fc1c494828fc8d8f141be115c54231bcbe38814c..2405f51b3e90f9dab947bcef12f778445f2a3f64 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -653,7 +653,7 @@ pub const Object = struct { }), debug_enums_fwd_ref, debug_globals_fwd_ref, - .{ .optimized = comp.root_mod.optimize_mode != .Debug }, + .{ .optimized = comp.root_mod.optimize_mode != .debug }, ); try builder.addNamedMetadata(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit}); @@ -1028,7 +1028,7 @@ pub const Object = struct { const optimize_mode = comp.root_mod.optimize_mode; - const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .Debug) + const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .debug) .None else .Aggressive; @@ -1299,7 +1299,7 @@ pub const Object = struct { .NoReturn = fn_info.return_type == .noreturn_type, }, .sp_flags = .{ - .Optimized = owner_mod.optimize_mode != .Debug, + .Optimized = owner_mod.optimize_mode != .debug, .Definition = true, .LocalToUnit = is_internal_linkage, }, @@ -2798,7 +2798,7 @@ pub const Object = struct { &o.builder, ); } - if (owner_mod.optimize_mode == .ReleaseSmall) { + if (owner_mod.optimize_mode == .small) { try attributes.addFnAttr(.minsize, &o.builder); try attributes.addFnAttr(.optsize, &o.builder); } diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index d8b8eede7c09febaf5485ef0c013fff94934d8ef..6e2d71994a6f67a10a9aa7723071c419cd1815e4 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -696,7 +696,7 @@ fn genBodyDebugScope( .{ .di_flags = .{ .StaticMember = true }, .sp_flags = .{ - .Optimized = mod.optimize_mode != .Debug, + .Optimized = mod.optimize_mode != .debug, .Definition = true, .LocalToUnit = true, // inline functions cannot be exported }, @@ -2516,7 +2516,7 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Er }, "", ); - } else if (owner_mod.optimize_mode == .Debug and !self.is_naked) { + } else if (owner_mod.optimize_mode == .debug and !self.is_naked) { // We avoid taking this path for naked functions because there's no guarantee that such // functions even have a valid stack pointer, making the `alloca` + `store` unsafe. @@ -4689,7 +4689,7 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { }, "", ); - } else if (mod.optimize_mode == .Debug) { + } else if (mod.optimize_mode == .debug) { const alloca = try self.buildZigAlloca(inst_ty, .none); try self.store(alloca, .none, arg_val, inst_ty, .normal); _ = try self.wip.callIntrinsic( @@ -4820,7 +4820,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu // unexpected call in the user's code. This is problematic if the code in question is // not ready to correctly make calls yet, such as in our early PIE startup code, or in // the early stages of a dynamic linker, etc. - if (!safety and owner_mod.optimize_mode == .Debug) { + if (!safety and owner_mod.optimize_mode == .debug) { return .none; } diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 2b953f3bbef4ac4924b37ac4cb3d8f524b7bc9d9..4ee131d079c666a52516e480137782e44f45a553 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -8339,9 +8339,9 @@ fn resolveCallingConventionValues( fn wantSafety(func: *Func) bool { return switch (func.mod.optimize_mode) { .Debug => true, - .ReleaseSafe => true, - .ReleaseFast => false, - .ReleaseSmall => false, + .safe => true, + .fast => false, + .small => false, }; } diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig index c5161485d377a68949901d6ed882346289a1c354..be9102f81ec684c11afe4cce59742823704b3175 100644 --- a/src/codegen/sparc64/CodeGen.zig +++ b/src/codegen/sparc64/CodeGen.zig @@ -4764,9 +4764,9 @@ fn truncRegister( fn wantSafety(self: *Self) bool { return switch (self.bin_file.comp.root_mod.optimize_mode) { .Debug => true, - .ReleaseSafe => true, - .ReleaseFast => false, - .ReleaseSmall => false, + .safe => true, + .fast => false, + .small => false, }; } diff --git a/src/codegen/wasm/Mir.zig b/src/codegen/wasm/Mir.zig index 454592c5d2198e14d895b2e19586775396ef5395..8e5f1c32f958d8ea2403ea2260a421da08e153c9 100644 --- a/src/codegen/wasm/Mir.zig +++ b/src/codegen/wasm/Mir.zig @@ -661,8 +661,8 @@ pub const Inst = struct { comptime { switch (builtin.mode) { - .Debug, .ReleaseSafe => {}, - .ReleaseFast, .ReleaseSmall => assert(@sizeOf(Data) == 4), + .debug, .safe => {}, + .fast, .small => assert(@sizeOf(Data) == 4), } } }; diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 1b29b50549173fe0d0855f541238971f8fcba181..da0ace1f6dd5fe09e00eaf3c7e5b572de2d2e50a 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -182502,8 +182502,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool { .slow_unaligned_mem_16, .slow_unaligned_mem_32, => switch (cg.mod.optimize_mode) { - .Debug, .ReleaseSafe, .ReleaseFast => null, - .ReleaseSmall => false, + .debug, .safe, .fast => null, + .small => false, }, .fast_11bytenop, .fast_15bytenop, @@ -182523,8 +182523,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool { .fast_vector_fsqrt, .fast_vector_shift_masks, => switch (cg.mod.optimize_mode) { - .Debug, .ReleaseSafe, .ReleaseFast => null, - .ReleaseSmall => true, + .debug, .safe, .fast => null, + .small => true, }, .mmx => false, .sahf => switch (cg.target.cpu.arch) { diff --git a/src/libs/libcxx.zig b/src/libs/libcxx.zig index 502199a58fbee46259a18257192e97d79cab3678..4036cec8f6447425bd9c7e8eaba5c60e2b33a17c 100644 --- a/src/libs/libcxx.zig +++ b/src/libs/libcxx.zig @@ -539,15 +539,15 @@ pub fn addCxxArgs( // is simple and works everywhere. try cflags.append("-D_LIBCPP_PSTL_BACKEND_SERIAL"); switch (optimize_mode) { - .Debug => { + .debug => { try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG"); try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE"); }, - .ReleaseFast, .ReleaseSmall => { + .fast, .small => { try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE"); try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_IGNORE"); }, - .ReleaseSafe => { + .safe => { try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST"); try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE"); }, diff --git a/src/libs/libunwind.zig b/src/libs/libunwind.zig index 82ef9c34bc3d76b5cdbf2306ff8faf2526f54cbb..46c4b0332aad75d110ab172ccc3209a8257c66b4 100644 --- a/src/libs/libunwind.zig +++ b/src/libs/libunwind.zig @@ -118,7 +118,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr // defines will be correct. try cflags.append("-D_LIBUNWIND_IS_NATIVE_ONLY"); - if (comp.root_mod.optimize_mode == .Debug) { + if (comp.root_mod.optimize_mode == .debug) { try cflags.append("-D_DEBUG"); } if (!comp.config.any_non_single_threaded) { diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index 99257442052cea392327370ca91879be1371cb3c..224b5ec27b4c0e8dac994ec4a54f85a689a11449 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -135,8 +135,8 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre }); switch (comp.compilerRtOptMode()) { - .Debug, .ReleaseSafe => try winpthreads_args.append("-DWINPTHREAD_DBG"), - .ReleaseFast, .ReleaseSmall => {}, + .debug, .safe => try winpthreads_args.append("-DWINPTHREAD_DBG"), + .fast, .small => {}, } for (mingw32_winpthreads_src) |dep| { diff --git a/src/link/C.zig b/src/link/C.zig index ae8526aafefb5adbcff87d1a90f789653e9faa8a..a6830126fb2f048af065093adf6e99e2778e0c88 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -429,7 +429,7 @@ pub fn createEmpty( .tag = .c, .comp = comp, .emit = emit, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .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 false, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 136c1184f64554dfcee7d60c7e044d662a778d82..1f756a5bf1bfd130f2fdc62c7d990e1a9320ff62 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -5598,11 +5598,11 @@ fn updateFuncInner( const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ .alignment = switch (nav.resolved.?.@"align") { .none => switch (mod.optimize_mode) { - .Debug, - .ReleaseSafe, - .ReleaseFast, + .debug, + .safe, + .fast, => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => target_util.minFunctionAlignment(target), + .small => target_util.minFunctionAlignment(target), }, else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), }.toStdMem(), @@ -6649,11 +6649,11 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { const target = &comp.root_mod.resolved_target.result; const alignment = switch (comp.root_mod.optimize_mode) { - .Debug, - .ReleaseSafe, - .ReleaseFast, + .debug, + .safe, + .fast, => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => target_util.minFunctionAlignment(target), + .small => target_util.minFunctionAlignment(target), }.toStdMem(); const parent_si = (try coff.pseudoSectionMapIndex( .@".thunks", diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d0448f575793e6af830d9ae3b37cf3ca827a89bb..cda6d5321069bfe23b53efb10eb6dc6da8a0bc6d 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -260,7 +260,7 @@ pub fn createEmpty( .tag = .elf, .comp = comp, .emit = emit, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .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, diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 9c0d1202776faa558015eec68b86fe3d3bbbe407..cd3378c8d69f457bb45e028def978067a219196d 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1299,7 +1299,7 @@ fn getNavShdrIndex( } if (nav_val.isUndef(zcu)) return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { - .Debug, .ReleaseSafe => { + .debug, .safe => { if (self.data_index) |symbol_index| return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ @@ -1311,7 +1311,7 @@ fn getNavShdrIndex( self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec); return osec; }, - .ReleaseFast, .ReleaseSmall => { + .fast, .small => { if (self.bss_index) |symbol_index| return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ @@ -1374,8 +1374,8 @@ fn updateNavCode( const target = &mod.resolved_target.result; const required_alignment = switch (nav.resolved.?.@"align") { .none => switch (mod.optimize_mode) { - .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => target_util.minFunctionAlignment(target), + .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), + .small => target_util.minFunctionAlignment(target), }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)), else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), }; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index a3ef197aba481bfb355d2d913efffbede87c55ae..128dbe9edb835fdd75409ea96eeb646d60882ff2 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -4782,11 +4782,11 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node break :a switch (nav.resolved.?.@"align") { else => |a| a.maxStrict(min), .none => switch (mod.optimize_mode) { - .Debug, - .ReleaseSafe, - .ReleaseFast, + .debug, + .safe, + .fast, => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => min, + .small => min, }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)), }; }, diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 715c0ba69f0c8f50ad6306ad7519c173a4d3dc0e..eaefd684d6f0582df96e1111033122290ee13297 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -208,8 +208,8 @@ pub fn createEmpty( const optimize_mode = comp.root_mod.optimize_mode; const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) { - .coff => optimize_mode != .Debug, - .elf => optimize_mode != .Debug and output_mode != .Obj, + .coff => optimize_mode != .debug, + .elf => optimize_mode != .debug and output_mode != .Obj, .wasm => output_mode != .Obj, else => unreachable, }; @@ -456,9 +456,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { if (comp.config.lto != .none) { switch (optimize_mode) { - .Debug => {}, - .ReleaseSmall => try argv.append("-OPT:lldlto=2"), - .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), + .debug => {}, + .small => try argv.append("-OPT:lldlto=2"), + .fast, .safe => try argv.append("-OPT:lldlto=3"), } } if (comp.config.output_mode == .Exe) { @@ -865,15 +865,15 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { 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"), + .debug => {}, + .small => try argv.append("--lto-O2"), + .fast, .safe => try argv.append("--lto-O3"), } } switch (comp.root_mod.optimize_mode) { - .Debug => {}, - .ReleaseSmall => try argv.append("-O2"), - .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), + .debug => {}, + .small => try argv.append("-O2"), + .fast, .safe => try argv.append("-O3"), } if (elf.entry_name) |name| { @@ -1416,9 +1416,9 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { if (comp.config.lto != .none) { switch (comp.root_mod.optimize_mode) { - .Debug => {}, - .ReleaseSmall => try argv.append("-O2"), - .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), + .debug => {}, + .small => try argv.append("-O2"), + .fast, .safe => try argv.append("-O3"), } } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 41d0c4fd5dc7a7854585b0a0d335c87a608e876c..543d803b11286b8a22155ba80d785012d9f49363 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -181,7 +181,7 @@ pub fn createEmpty( .tag = .macho, .comp = comp, .emit = emit, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .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, diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 8d7407a0a397e9f4f0df654ef4eb45fe19e0e108..71a4bc6dc70c0465a079f035d459a07d8720ceed 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -946,8 +946,8 @@ fn updateNavCode( const target = &mod.resolved_target.result; const required_alignment = switch (nav.resolved.?.@"align") { .none => switch (mod.optimize_mode) { - .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), - .ReleaseSmall => target_util.minFunctionAlignment(target), + .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), + .small => target_util.minFunctionAlignment(target), }, else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), }; @@ -1172,8 +1172,8 @@ fn getNavOutputSection( if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?; if (nav_val.isUndef(zcu)) return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { - .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?, - .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?, + .debug, .safe => macho_file.zig_data_sect_index.?, + .fast, .small => macho_file.zig_bss_sect_index.?, }; for (code) |byte| { if (byte != 0) break; diff --git a/src/main.zig b/src/main.zig index 4fe6de03247578285c251daed3eb8d3982ac5dca..94011c81f9215df1da00328f221c41e42b9bc214 100644 --- a/src/main.zig +++ b/src/main.zig @@ -44,9 +44,9 @@ pub const std_options: std.Options = .{ .logFn = log, .log_level = switch (builtin.mode) { - .Debug => .debug, - .ReleaseSafe, .ReleaseFast => .info, - .ReleaseSmall => .err, + .debug => .debug, + .safe, .fast => .info, + .small => .err, }, }; pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; @@ -158,8 +158,8 @@ pub fn log( const use_safe_allocator = build_options.debug_gpa or (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, + .debug, .safe => true, + .fast, .small => false, }); var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{ @@ -360,7 +360,7 @@ fn mainArgs( .prepend_zig_exe_path = true, .prepend_seed = true, .debug_env_var = .ZIG_DEBUG_MAKER, - .release_mode = .ReleaseSafe, + .release_mode = .safe, }); }, .clang, .@"-cc1", .@"-cc1as" => { @@ -568,10 +568,10 @@ const usage_build_generic = \\Per-Module Compile Options: \\ -target [name] -- see the targets command \\ -O [mode] Choose what to optimize for - \\ Debug (default) Optimizations off, safety on - \\ ReleaseFast Optimize for performance, safety off - \\ ReleaseSafe Optimize for performance, safety on - \\ ReleaseSmall Optimize for small binary, safety off + \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed + \\ fast Prioritize runtime performance. Safety checks off. + \\ safe Enable both safety checks and machine code optimizations + \\ small Prioritize small binary size. Safety checks off. \\ -ofmt=[fmt] Override target object format \\ elf Executable and Linking Format \\ c C source code @@ -994,7 +994,7 @@ fn buildOutputType( var minor_subsystem_version: ?u16 = null; var mingw_unicode_entry_point: bool = false; var enable_link_snapshots: bool = false; - var debug_compiler_runtime_libs: ?std.lang.OptimizeMode = null; + var debug_compiler_runtime_libs: ?std.lang.Optimize = null; var install_name: ?[]const u8 = null; var hash_style: link.File.Lld.Elf.HashStyle = .both; var entitlements: ?[]const u8 = null; @@ -1433,7 +1433,7 @@ fn buildOutputType( enable_link_snapshots = true; } } else if (mem.eql(u8, arg, "--debug-rt")) { - debug_compiler_runtime_libs = .Debug; + debug_compiler_runtime_libs = .debug; } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| { debug_compiler_runtime_libs = parseOptimizeMode(rest); } else if (mem.eql(u8, arg, "--debug-incremental")) { @@ -2271,18 +2271,18 @@ fn buildOutputType( if (mem.eql(u8, level, "s") or mem.eql(u8, level, "z")) { - mod_opts.optimize_mode = .ReleaseSmall; + mod_opts.optimize_mode = .small; } else if (mem.eql(u8, level, "1") or mem.eql(u8, level, "2") or mem.eql(u8, level, "3") or mem.eql(u8, level, "4") or mem.eql(u8, level, "fast")) { - mod_opts.optimize_mode = .ReleaseFast; + mod_opts.optimize_mode = .fast; } else if (mem.eql(u8, level, "g") or mem.eql(u8, level, "0")) { - mod_opts.optimize_mode = .Debug; + mod_opts.optimize_mode = .debug; } else { try cc_argv.appendSlice(arena, it.other_args); } @@ -2356,9 +2356,9 @@ fn buildOutputType( // `sanitize_c` will resolve to! So we either have to pick `off` or `full`. // // `full` has the potential to be problematic if `optimize_mode` turns out to - // be `ReleaseFast`/`ReleaseSmall` because the user will get a slower and larger + // be `fast`/`small` because the user will get a slower and larger // binary than expected. On the other hand, if `optimize_mode` turns out to be - // `Debug`/`ReleaseSafe`, `off` would mean UBSan would unexpectedly be disabled. + // `debug`/`safe`, `off` would mean UBSan would unexpectedly be disabled. // // `off` seems very slightly less bad, so let's go with that. mod_opts.sanitize_c = .off; @@ -2972,8 +2972,8 @@ fn buildOutputType( } if (mod_opts.sanitize_c) |wsc| { - if (wsc != .off and mod_opts.optimize_mode == .ReleaseFast) { - mod_opts.optimize_mode = .ReleaseSafe; + if (wsc != .off and mod_opts.optimize_mode == .fast) { + mod_opts.optimize_mode = .safe; } } @@ -4875,7 +4875,7 @@ const JitCmdOptions = struct { /// Send error bundles via std.zig.Server over stdout server: bool = false, debug_env_var: EnvVar = .ZIG_DEBUG_CMD, - release_mode: std.lang.OptimizeMode = .ReleaseFast, + release_mode: std.lang.Optimize = .fast, }; fn jitCmd( @@ -4926,11 +4926,11 @@ fn jitCmdInner( const self_exe_path = process.executablePathAlloc(io, arena) catch |err| fatal("unable to find self exe path: {t}", .{err}); - const optimize_mode: std.lang.OptimizeMode = if (options.debug_env_var.isSet(environ_map)) - .Debug + const optimize_mode: std.lang.Optimize = if (options.debug_env_var.isSet(environ_map)) + .debug else options.release_mode; - const strip = optimize_mode != .Debug; + const strip = optimize_mode != .debug; var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); @@ -6008,9 +6008,8 @@ fn parseRcIncludes(arg: []const u8) std.zig.RcIncludes { fatal("unsupported rc includes type: {q}", .{arg}); } -fn parseOptimizeMode(s: []const u8) std.lang.OptimizeMode { - return stringToEnum(std.lang.OptimizeMode, s) orelse - fatal("unrecognized optimization mode: {q}", .{s}); +fn parseOptimizeMode(s: []const u8) std.lang.Optimize { + return std.lang.Optimize.fromString(s) orelse fatal("unrecognized optimization mode: {q}", .{s}); } fn parseWasiExecModel(s: []const u8) std.lang.WasiExecModel { diff --git a/src/target.zig b/src/target.zig index ca3b3d93de1a74114d621c8065e96d561e413dc8..0ed4053701fd696db7540b42dbf5aaf890e47921 100644 --- a/src/target.zig +++ b/src/target.zig @@ -357,12 +357,12 @@ pub fn libcProvidesStackProtector(target: *const std.Target) bool { /// Returns true if `@returnAddress()` is supported by the target and has a /// reasonably performant implementation for the requested optimization mode. -pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.OptimizeMode) bool { +pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.Optimize) bool { return switch (target.cpu.arch) { // Emscripten currently implements `emscripten_return_address()` by calling // out into JavaScript and parsing a stack trace, which introduces significant // overhead that we would prefer to avoid in release builds. - .wasm32, .wasm64 => target.os.tag == .emscripten and optimize == .Debug, + .wasm32, .wasm64 => target.os.tag == .emscripten and optimize == .debug, .bpfel, .bpfeb => false, .spirv32, .spirv64 => false, else => true, @@ -417,11 +417,11 @@ pub fn hasDebugInfo(target: *const std.Target) bool { }; } -pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.OptimizeMode { +pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.Optimize { if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) { - return .ReleaseSmall; + return .small; } else { - return .ReleaseFast; + return .fast; } } diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 192afbe68d030d894827f1b0caa642ba8f79ff0c..d13fc8e83d36590bb20b329f3accd39eae411a4d 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -498,7 +498,7 @@ test "array coercion to undefined at runtime" { @setRuntimeSafety(true); - if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { + if (builtin.mode != .debug and builtin.mode != .safe) { return error.SkipZigTest; } diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 780ed846d34a1f4cc45f6fa40467b97e93a2cdb0..76b21b6f15316a95c3ee6d98a759ff06e8c03715 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -1678,7 +1678,7 @@ test "runtime isNan(inf * 0)" { test "optimized float mode" { if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; - if (builtin.mode == .Debug) return error.SkipZigTest; + if (builtin.mode == .debug) return error.SkipZigTest; const big = 0x1p40; const small = 0.001; diff --git a/test/behavior/int128.zig b/test/behavior/int128.zig index ce69d80522516c71cc586b84bb3784f0ba9c75e6..f02aed4f90c68d6676404aed8e728b2b9a4916ba 100644 --- a/test/behavior/int128.zig +++ b/test/behavior/int128.zig @@ -31,7 +31,7 @@ test "undefined 128 bit int" { @setRuntimeSafety(true); // TODO implement @setRuntimeSafety - if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { + if (builtin.mode != .debug and builtin.mode != .safe) { return error.SkipZigTest; } diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 1fd570b4ed40b6a50d2085c8d65a32fa941b36fc..f9a48477a714b250696652184e1511ccf86bae28 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -16754,7 +16754,7 @@ test "CFF: Zig returns to C" { } test "CFF: C passes to Zig" { if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; @@ -16764,7 +16764,7 @@ test "CFF: C passes to Zig" { try expectOk(c_send_CFF()); } test "CFF: C returns to Zig" { - if (builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; @@ -16920,7 +16920,7 @@ extern fn c_f16_struct(f16_struct) f16_struct; test "f16 struct" { if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.mode != .Debug) return error.SkipZigTest; + if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; diff --git a/test/cases/compile_errors/invalid_member_of_builtin_enum.zig b/test/cases/compile_errors/invalid_member_of_builtin_enum.zig index 48f1012c1f6884d6a34c2255edd9e2924743c1b1..9902f027bf45c5db93744caa8242194df29a3f41 100644 --- a/test/cases/compile_errors/invalid_member_of_builtin_enum.zig +++ b/test/cases/compile_errors/invalid_member_of_builtin_enum.zig @@ -6,5 +6,5 @@ export fn entry() void { // error // -// :3:35: error: enum 'lang.OptimizeMode' has no member named 'x86' +// :3:35: error: enum 'lang.Optimize' has no member named 'x86' // : note: enum declared here diff --git a/test/src/ErrorTrace.zig b/test/src/ErrorTrace.zig index f6f80f8b138d2f7a663b4fe1d5d8d58bc8ef43de..c4150eded5d4b17fffc2a386d3c7b9411ded6665 100644 --- a/test/src/ErrorTrace.zig +++ b/test/src/ErrorTrace.zig @@ -60,9 +60,9 @@ fn addCaseConfig( const b = self.b; const error_tracing: bool = tracing: { - if (optimize == .Debug) break :tracing true; + if (optimize == .debug) break :tracing true; if (backend != .llvm) break :tracing true; - if (optimize == .ReleaseSmall) break :tracing false; + if (optimize == .small) break :tracing false; for (case.disable_trace_optimized) |disable| { const d_arch, const d_os = disable; if (target.result.cpu.arch == d_arch and target.result.os.tag == d_os) { diff --git a/test/standalone/dependency_options/build.zig b/test/standalone/dependency_options/build.zig index 8966920617d0a9bd1c851b96a83abc1e617e6ba0..f56bef5ae48942740f0a23161357876c3f70f7e9 100644 --- a/test/standalone/dependency_options/build.zig +++ b/test/standalone/dependency_options/build.zig @@ -11,11 +11,11 @@ pub fn build(b: *std.Build) !void { const none_specified_mod = none_specified.module("dummy"); if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed; const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) { - .off => .Debug, + .off => .debug, .any => unreachable, - .fast => .ReleaseFast, - .safe => .ReleaseSafe, - .small => .ReleaseSmall, + .fast => .fast, + .safe => .safe, + .small => .small, }; if (none_specified_mod.optimize.? != expected_optimize) return error.TestFailed; @@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void { const all_specified = b.dependency("other", .{ .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), - .optimize = @as(std.builtin.OptimizeMode, .ReleaseSafe), + .optimize = @as(std.builtin.OptimizeMode, .safe), .bool = @as(bool, true), .int = @as(i64, 123), .float = @as(f64, 0.5), @@ -66,11 +66,11 @@ pub fn build(b: *std.Build) !void { if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed; if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed; if (all_specified_mod.resolved_target.?.result.abi != .gnu) return error.TestFailed; - if (all_specified_mod.optimize.? != .ReleaseSafe) return error.TestFailed; + if (all_specified_mod.optimize.? != .safe) return error.TestFailed; const all_specified_optional = b.dependency("other", .{ .target = @as(?std.Build.ResolvedTarget, b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu })), - .optimize = @as(?std.builtin.OptimizeMode, .ReleaseSafe), + .optimize = @as(?std.builtin.OptimizeMode, .safe), .bool = @as(?bool, true), .int = @as(?i64, 123), .float = @as(?f64, 0.5), @@ -92,7 +92,7 @@ pub fn build(b: *std.Build) !void { const all_specified_literal = b.dependency("other", .{ .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), - .optimize = .ReleaseSafe, + .optimize = .safe, .bool = true, .int = 123, .float = 0.5, @@ -130,7 +130,7 @@ pub fn build(b: *std.Build) !void { // to the same cached dependency instance. const all_specified_alt = b.dependency("other", .{ .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), - .optimize = "ReleaseSafe", + .optimize = "safe", .bool = .true, .int = "123", .float = @as(f16, 0.5), diff --git a/test/standalone/simple/build.zig b/test/standalone/simple/build.zig index af9da93a2b8a947ad9ccd72c547eb478217330f3..a61f2f1e975a1c3e46b1546791743842773e92de 100644 --- a/test/standalone/simple/build.zig +++ b/test/standalone/simple/build.zig @@ -13,26 +13,26 @@ pub fn build(b: *std.Build) void { var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined; var optimize_modes_len: usize = 0; if (!skip_debug) { - optimize_modes_buf[optimize_modes_len] = .Debug; + optimize_modes_buf[optimize_modes_len] = .debug; optimize_modes_len += 1; } if (!skip_release_safe) { - optimize_modes_buf[optimize_modes_len] = .ReleaseSafe; + optimize_modes_buf[optimize_modes_len] = .safe; optimize_modes_len += 1; } if (!skip_release_fast) { - optimize_modes_buf[optimize_modes_len] = .ReleaseFast; + optimize_modes_buf[optimize_modes_len] = .fast; optimize_modes_len += 1; } if (!skip_release_small) { - optimize_modes_buf[optimize_modes_len] = .ReleaseSmall; + optimize_modes_buf[optimize_modes_len] = .small; optimize_modes_len += 1; } const optimize_modes = optimize_modes_buf[0..optimize_modes_len]; for (cases) |case| { for (optimize_modes) |optimize| { - if (!case.all_modes and optimize != .Debug) continue; + if (!case.all_modes and optimize != .debug) continue; if (case.os_filter) |os_tag| { if (os_tag != builtin.os.tag) continue; } diff --git a/test/tests.zig b/test/tests.zig index 78f397d3f4e0c47053d98c5a51049a8dd7507fa9..9a11d7c496a5179e02c74969f4481034764baa55 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -23,7 +23,7 @@ pub const LinkContext = @import("src/Link.zig"); const ModuleTestTarget = struct { linkage: ?std.builtin.LinkMode = null, target: std.Target.Query = .{}, - optimize_mode: std.builtin.OptimizeMode = .Debug, + optimize_mode: std.builtin.OptimizeMode = .debug, link_libc: ?bool = null, single_threaded: ?bool = null, use_llvm: ?bool = null, @@ -57,38 +57,38 @@ const module_test_targets = blk: { }, .{ - .optimize_mode = .ReleaseFast, + .optimize_mode = .fast, }, .{ .link_libc = true, - .optimize_mode = .ReleaseFast, + .optimize_mode = .fast, }, .{ - .optimize_mode = .ReleaseFast, + .optimize_mode = .fast, .single_threaded = true, }, .{ - .optimize_mode = .ReleaseSafe, + .optimize_mode = .safe, }, .{ .link_libc = true, - .optimize_mode = .ReleaseSafe, + .optimize_mode = .safe, }, .{ - .optimize_mode = .ReleaseSafe, + .optimize_mode = .safe, .single_threaded = true, }, .{ - .optimize_mode = .ReleaseSmall, + .optimize_mode = .small, }, .{ .link_libc = true, - .optimize_mode = .ReleaseSmall, + .optimize_mode = .small, }, .{ - .optimize_mode = .ReleaseSmall, + .optimize_mode = .small, .single_threaded = true, }, @@ -200,7 +200,7 @@ const module_test_targets = blk: { // }, // .use_llvm = false, // .use_lld = false, - // .optimize_mode = .ReleaseFast, + // .optimize_mode = .fast, // .strip = true, // .skip_modules = &.{"std"}, // TODO get these passing //}, @@ -213,7 +213,7 @@ const module_test_targets = blk: { // }, // .use_llvm = false, // .use_lld = false, - // .optimize_mode = .ReleaseFast, + // .optimize_mode = .fast, // .strip = true, // .skip_modules = &.{"std"}, // TODO get these passing //}, @@ -1257,7 +1257,7 @@ const module_test_targets = blk: { // }, // .use_llvm = false, // .use_lld = false, - // .optimize_mode = .ReleaseFast, + // .optimize_mode = .fast, // .strip = true, //}, @@ -2063,7 +2063,7 @@ const c_abi_targets = blk: { const LinkTarget = struct { target: std.Target.Query = .{}, - optimize_mode: std.builtin.OptimizeMode = .Debug, + optimize_mode: std.builtin.OptimizeMode = .debug, link_libc: bool = false, use_llvm: bool = false, use_lld: bool = false, @@ -2368,7 +2368,7 @@ pub fn addStackTraceTests( .root_module = b.createModule(.{ .root_source_file = b.path("test/src/convert-stack-trace.zig"), .target = b.graph.host, - .optimize = .Debug, + .optimize = .debug, }), }); @@ -2422,7 +2422,7 @@ pub fn addErrorTraceTests( .root_module = b.createModule(.{ .root_source_file = b.path("test/src/convert-stack-trace.zig"), .target = b.graph.host, - .optimize = .Debug, + .optimize = .debug, }), }); @@ -2486,10 +2486,10 @@ pub fn addStandaloneTests( .enable_ios_sdk = enable_ios_sdk, .enable_macos_sdk = enable_macos_sdk, .enable_symlinks_windows = enable_symlinks_windows, - .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null, - .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null, - .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null, - .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null, + .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .debug) == null, + .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .safe) == null, + .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .fast) == null, + .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .small) == null, }); const test_cases_dep_step = test_cases_dep.builder.default_step; test_cases_dep_step.name = b.dupe(test_cases_dep_name); @@ -3057,7 +3057,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt if (use_llvm) |x| return x; if (query.ofmt == .c) return false; switch (optimize_mode) { - .Debug => {}, + .debug => {}, else => return true, } const cpu_arch = query.cpu_arch orelse builtin.cpu.arch; @@ -3314,7 +3314,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons .root_module = b.createModule(.{ .root_source_file = b.path("tools/incr-check.zig"), .target = b.graph.host, - .optimize = .Debug, + .optimize = .debug, }), }); diff --git a/tools/doctest.zig b/tools/doctest.zig index d1d7919a51f299ecea3914ac8307d6b6741723a6..fcd67e8458a31ea03323b87cbfb222fc31852f94 100644 --- a/tools/doctest.zig +++ b/tools/doctest.zig @@ -915,11 +915,11 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code { while (it.next()) |prefixed_line| { const line = skipPrefix(prefixed_line); if (mem.startsWith(u8, line, "optimize=")) { - mode = std.meta.stringToEnum(std.builtin.OptimizeMode, line["optimize=".len..]) orelse - fatal("bad optimization mode line: '{s}'", .{line}); + mode = std.builtin.Optimize.fromString(line["optimize=".len..]) orelse + fatal("bad optimization mode line: {q}", .{line}); } else if (mem.startsWith(u8, line, "link_mode=")) { link_mode = std.meta.stringToEnum(std.builtin.LinkMode, line["link_mode=".len..]) orelse - fatal("bad link mode line: '{s}'", .{line}); + fatal("bad link mode line: {q}", .{line}); } else if (mem.startsWith(u8, line, "link_object=")) { try link_objects.append(arena, line["link_object=".len..]); } else if (mem.startsWith(u8, line, "additional_option=")) { diff --git a/tools/migrate_langref.zig b/tools/migrate_langref.zig index 2810bfd3eaa60752eaa075746d18735a441a2760..4c48113a8698f91067d5b7887adb3286df3bc351 100644 --- a/tools/migrate_langref.zig +++ b/tools/migrate_langref.zig @@ -319,7 +319,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {s}", .{code_kind_str}); } - var mode: std.builtin.OptimizeMode = .Debug; + var mode: std.builtin.OptimizeMode = .debug; var link_objects = std.array_list.Managed([]const u8).init(arena); var target_str: ?[]const u8 = null; var link_libc = false; @@ -403,7 +403,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp }, } - if (mode != .Debug) + if (mode != .debug) try code.print("// optimize={s}\n", .{@tagName(mode)}); for (link_objects.items) |link_object| { -- 2.54.0 From f2c2ee28cbb2aad3943a5726ea5d1dfa427c96af Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 19 Jul 2026 21:28:40 -0700 Subject: [PATCH 006/215] std.lang.Optimize: provide alternative to std.debug.runtime_safety --- lib/std/debug.zig | 13 ++++++------- lib/std/lang.zig | 9 +++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 8aaee0e29edaba4523a70710de7eca31cf0bc078..898ae314d9084e35fed670b03854959ec06beead 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -237,13 +237,12 @@ pub const Symbol = struct { }; }; -/// Deprecated because it returns the optimization mode of the standard -/// library, when the caller probably wants to use the optimization mode of -/// their own module. -pub const runtime_safety = switch (builtin.mode) { - .debug, .safe => true, - .fast, .small => false, -}; +/// Deprecated in favor of `std.lang.Optimize.runtimeSafety`, to be removed after 0.18.0 +/// +/// Returns whether the standard library has safety checks enabled. Callsites +/// likely would rather know whether their own module's optimization mode +/// (found via `@import("builtin").optimize`) has safety checks enabled. +pub const runtime_safety = builtin.mode.runtimeSafety(); /// Whether we can unwind the stack on this target, allowing capturing and/or printing the current /// stack trace. It is still legal to call `captureCurrentStackTrace`, `writeCurrentStackTrace`, and diff --git a/lib/std/lang.zig b/lib/std/lang.zig index daa2482eec7429bcd90a83ae2e2515681be29187..2f0868c39331456b03f055cafd8546f19ac51b07 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -144,6 +144,15 @@ pub const Optimize = enum { .{ "small", .small }, }).get(s); } + + /// Returns whether illegal behavior safety checks are enabled based on the + /// provided optimization mode. + pub fn runtimeSafety(o: @This()) bool { + return switch (o) { + .debug, .safe => true, + .fast, .small => false, + }; + } }; /// The calling convention of a function defines how arguments and return values are passed, as well -- 2.54.0 From 8807e934d840906f4b5bd2ad8fdaa6967c1922ea Mon Sep 17 00:00:00 2001 From: Krzysztof Wolicki Date: Mon, 20 Jul 2026 00:05:30 +0200 Subject: [PATCH 007/215] Remove things deprecated in 0.16.0 --- lib/std/Target.zig | 3 --- lib/std/zig.zig | 17 ----------------- src/link/Lld.zig | 2 -- 3 files changed, 22 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index e9105c4737318576719795cd67e70e6b05d293e4..6124ffd96597d33dbd1027ae8b5757989b536c7a 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1194,9 +1194,6 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { }; } -/// Deprecated; use 'std.zig.Subsystem' instead. To be removed after 0.16.0 is tagged. -pub const SubSystem = std.zig.Subsystem; - pub const Cpu = struct { /// Architecture arch: Arch, diff --git a/lib/std/zig.zig b/lib/std/zig.zig index fafb3cac422ac17b36dee498ddecf014366fbc91..4c41d56845f7ebd32bb83a51d2ec182b7e4e7154 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -386,23 +386,6 @@ pub const Subsystem = enum { efi_boot_service_driver, efi_rom, efi_runtime_driver, - - /// Deprecated; use '.console' instead. To be removed after 0.16.0 is tagged. - pub const Console: Subsystem = .console; - /// Deprecated; use '.windows' instead. To be removed after 0.16.0 is tagged. - pub const Windows: Subsystem = .windows; - /// Deprecated; use '.posix' instead. To be removed after 0.16.0 is tagged. - pub const Posix: Subsystem = .posix; - /// Deprecated; use '.native' instead. To be removed after 0.16.0 is tagged. - pub const Native: Subsystem = .native; - /// Deprecated; use '.efi_application' instead. To be removed after 0.16.0 is tagged. - pub const EfiApplication: Subsystem = .efi_application; - /// Deprecated; use '.efi_boot_service_driver' instead. To be removed after 0.16.0 is tagged. - pub const EfiBootServiceDriver: Subsystem = .efi_boot_service_driver; - /// Deprecated; use '.efi_rom' instead. To be removed after 0.16.0 is tagged. - pub const EfiRom: Subsystem = .efi_rom; - /// Deprecated; use '.efi_runtime_driver' instead. To be removed after 0.16.0 is tagged. - pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver; }; pub const CompressDebugSections = enum(u2) { none, zlib, zstd }; diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 715c0ba69f0c8f50ad6306ad7519c173a4d3dc0e..b9b3437be14d96d1146eb870834e8d91b0c12720 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -99,8 +99,6 @@ pub const Elf = struct { bind_global_refs_locally: bool, pub const HashStyle = enum { sysv, gnu, both }; pub const SortSection = enum { name, alignment }; - /// Deprecated; use 'std.zig.CompressDebugSections' instead. To be removed after 0.16.0 is tagged. - pub const CompressDebugSections = std.zig.CompressDebugSections; fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf { const PtrWidth = enum { p32, p64 }; -- 2.54.0 From 5eb216744aa62c5cafa0891fd5a7630ab52c2acf Mon Sep 17 00:00:00 2001 From: rpkak Date: Sun, 14 Jun 2026 14:29:54 +0200 Subject: [PATCH 008/215] compiler_rt: remove __memset --- lib/compiler_rt.zig | 7 ------- test/standalone/compiler_rt_panic/main.c | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 0a8621ed13e8e6b4422b7b2554bf29955282f91c..e8a7d8a857f57d56dc737de84d3e0eeddb97a8c2 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -302,7 +302,6 @@ comptime { _ = @import("compiler_rt/memcpy.zig"); if (!ofmt_c) { symbol(&memset, "memset"); - symbol(&__memset, "__memset"); } _ = @import("compiler_rt/memmove.zig"); symbol(&memcmp, "memcmp"); @@ -667,12 +666,6 @@ pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 { return dest; } -pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { - if (dest_n < n) - @panic("buffer overflow"); - return memset(dest, c, n); -} - pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { @setRuntimeSafety(false); diff --git a/test/standalone/compiler_rt_panic/main.c b/test/standalone/compiler_rt_panic/main.c index be64216ab7e794616bd77cf5e61980f5fdc381c8..a11df761aaa60fc388163ccd76e82906767d146f 100644 --- a/test/standalone/compiler_rt_panic/main.c +++ b/test/standalone/compiler_rt_panic/main.c @@ -1,11 +1,11 @@ #include -void* __memset(void* dest, char c, size_t n, size_t dest_n); +void *__memset_chk(void *dest, int c, size_t n, size_t dest_n); char foo[128]; int main() { - __memset(&foo[0], 0xff, 128, 128); + __memset_chk(&foo[0], 0xff, 128, 128); return foo[64]; } -- 2.54.0 From 0e61c9aba3ca641d7cdade43ef239d1a2c9ab58d Mon Sep 17 00:00:00 2001 From: rpkak Date: Sun, 14 Jun 2026 14:32:34 +0200 Subject: [PATCH 009/215] compiler_rt: fix arg type of memset and __memset_chk --- lib/compiler_rt.zig | 5 +++-- lib/compiler_rt/ssp.zig | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index e8a7d8a857f57d56dc737de84d3e0eeddb97a8c2..8e2fa4f0d5b8b85a0fcb14fdabd2ed1aca70f77d 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -649,14 +649,15 @@ inline fn negXi2(comptime T: type, a: T) T { return -a; } -pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 { +pub fn memset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { @setRuntimeSafety(false); + const b: u8 = @truncate(@as(c_uint, @bitCast(c))); if (len != 0) { var d = dest.?; var n = len; while (true) { - d[0] = c; + d[0] = b; n -= 1; if (n == 0) break; d += 1; diff --git a/lib/compiler_rt/ssp.zig b/lib/compiler_rt/ssp.zig index 42d088eeb8ab714b4b3d9ac79e579634ffff11a3..20468b0c0de8eb23cc9dff83c3e1bcbf46417f57 100644 --- a/lib/compiler_rt/ssp.zig +++ b/lib/compiler_rt/ssp.zig @@ -17,7 +17,7 @@ const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; const builtin = @import("builtin"); -extern fn memset(dest: ?[*]u8, c: u8, n: usize) callconv(.c) ?[*]u8; +extern fn memset(dest: ?[*]u8, c: c_int, n: usize) callconv(.c) ?[*]u8; extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; @@ -138,7 +138,7 @@ fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callc return memmove(dest, src, n); } -fn __memset_chk(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { +fn __memset_chk(dest: ?[*]u8, c: c_int, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { if (dest_n < n) __chk_fail(); return memset(dest, c, n); } -- 2.54.0 From 2c894ce206036cb6fa155dd431444fa4f35d5cde Mon Sep 17 00:00:00 2001 From: rpkak Date: Sat, 13 Jun 2026 12:41:14 +0200 Subject: [PATCH 010/215] compiler_rt: optimize memset --- lib/compiler_rt.zig | 74 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 8e2fa4f0d5b8b85a0fcb14fdabd2ed1aca70f77d..f042d0076e62740c50d61b4e28b8b3ddb07012f3 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -649,8 +649,73 @@ inline fn negXi2(comptime T: type, a: T) T { return -a; } -pub fn memset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { - @setRuntimeSafety(false); +fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void { + if (size > @sizeOf(usize)) { + d[0..size].* = @splat(b); + } else { + const T = @Int(.unsigned, 8 * size); + var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt. + @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b); + @as(*align(1) T, @ptrCast(d)).* = splatted; + } +} + +fn shortMemset( + log_min: comptime_int, + log_max: comptime_int, + d: [*]u8, + b: u8, + len: usize, +) void { + if (log_min + 1 != log_max) { + const mid = (log_min + log_max) / 2; + if (len > 1 << mid) { + shortMemset(mid, log_max, d, b, len); + } else { + shortMemset(log_min, mid, d, b, len); + } + } else { + const size = 1 << log_min; + + memsetSmallPowerOf2(d, b, size); + memsetSmallPowerOf2(d + len - size, b, size); + } +} + +fn fastMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { + const b: u8 = @truncate(@as(c_uint, @bitCast(c))); + const n = std.simd.suggestVectorLength(u8) orelse @sizeOf(usize); + + const d = dest.?; + + if (len > 2 * n) { + memsetSmallPowerOf2(d, b, n); + + const begin_aligned = std.mem.alignBackward(usize, @intFromPtr(d) + n, n); + const end_aligned = std.mem.alignForward(usize, @intFromPtr(d) + len - n, n); + + const aligned_ptr: [*]align(n) u8 = @ptrFromInt(begin_aligned); + + var i: usize = 0; + while (true) { + memsetSmallPowerOf2(aligned_ptr + n * i, b, n); + + i += 1; + if (i == @divExact(end_aligned - begin_aligned, n)) + break; + } + + memsetSmallPowerOf2(d + len - n, b, n); + } else { + if (len == 0) return dest; + + shortMemset(0, @ctz(@as(usize, 2 * n)), d, b, len); + } + + return dest; +} + +fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { const b: u8 = @truncate(@as(c_uint, @bitCast(c))); if (len != 0) { @@ -667,6 +732,11 @@ pub fn memset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { return dest; } +pub const memset = if (builtin.optimize == .small) + smallMemset +else + fastMemset; + pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { @setRuntimeSafety(false); -- 2.54.0 From 37909d3170769ee361f4e62cb9558efe12630781 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 20 Jul 2026 11:55:10 +0100 Subject: [PATCH 011/215] std.Progress: fix assertion failure when IPC slots are exhausted --- lib/std/Progress.zig | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 1c49983d54db855297db8fb2d37d6d560a8116d8..b519265a9d6f54a47e210d4672e87a22f588a29d 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -442,7 +442,15 @@ pub const Node = struct { global_progress.ipc_files[slot] = file; storageByIndex(index).setIpcIndex(.{ .slot = slot, .generation = generation }); break; - } else file.close(io); + } else { + // There was no IPC slot available, so we'll drop this node's IPC info and just close + // the fd. To avoid an old `estimated_total_items` or `completed_count` value still + // being rendered for the node, we'll zero that field out (and the user is not allowed + // to change it because they think we're doing IPC). + file.close(io); + @atomicStore(u32, &storageByIndex(index).completed_count, 0, .monotonic); + @atomicStore(u32, &storageByIndex(index).estimated_total_count, 0, .monotonic); + } } pub fn setIpcIndex(node: Node, ipc_index: Ipc.Index) void { @@ -452,7 +460,11 @@ pub const Node = struct { /// Not thread-safe. pub fn takeIpcIndex(node: Node) ?Ipc.Index { const storage = storageByIndex(node.index.unwrap() orelse return null); - assert(storage.estimated_total_count == std.math.maxInt(u32)); + switch (storage.estimated_total_count) { + std.math.maxInt(u32) => {}, // indicates that there is an IPC index in `completed_count` + 0 => return null, // `setIpcFile` failed so we don't have an IPC index for this node + else => unreachable, // not an IPC node + } @atomicStore(u32, &storage.estimated_total_count, 0, .monotonic); return @bitCast(storage.completed_count); } -- 2.54.0 From 7faf6be3535195b96b69fb9b8d12f16015d7ec36 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 19 Jul 2026 12:41:03 +0100 Subject: [PATCH 012/215] link.Lld: handle errors properly in ZigLLVMWriteArchive So... it turns out https://codeberg.org/ziglang/zig/issues/31520 is probably our fault! This commit does not close that issue, but it at least makes some progress. LLVM's `Error` type is basically `anyerror!void`, and when an error occurs, it can detect that the caller didn't look at the error code, in which case it will abort with an error message. Our implementation of `ZigLLVMWriteArchive` was checking *that* there was an error, but not what that error *was*, so was triggering this code path. (I think that LLVM's approach to error handling here is unnecessarily dangerous, but whatcha gonna do :shrug:) It is possible for the "no such file or directory" error to occur in this function due to a TOCTOU bug. If we are producing a static library, and some object file is deleted after the Zig frontend checks that it exists but *before* `ZigLLVMWriteArchive` has a chance to read the file, LLVM will report that the input file does not exist. The reason I found this bug is that I was able to somewhat consistently trigger the same condition by running a faulty build script which had duplicated steps. Consider a case where build step A and B generate the exact same object file, using the same options etc; and build step C depends on A, and puts that object file into a static library. At some point, step A and B both start running. Step A finishes first, placing an object file into the cache directory. The build system then starts the dependent step C. The compiler frontend confirms that the object file (in the cache directory) exists, as expected, and passes it off to `ZigLLVMWriteArchive`---but around this time, step B finishes, and begins writing the *new* file. Depending on how LLVM writes that output file, there may be a period of time where the file does not exist or is truncated, either of which could cause `ZigLLVMWriteArchive` to fail. The reproduction I described above does not explain #31520, because it relies on a faulty build script (where the same object file is being generated by multiple identical build steps), but that is not happening in #31520. It also relies on building a static library, which again, is not happening in #31520. Instead, if #31520 is indeed coming from this function (which I believe is the most likely explanation), it must be that #31520 is caused by a compiler bug which ultimately has the same effect (an object file in the cache being overwritten while being used to build a static library) This makes sense, because in many compilations we *do* build several static libraries: our vendored implementations of libraries, including musl libc, libc++, libunwind, etc. However, this still doesn't fully explain the bug. When we build these libraries, we create a `Compilation` with a bunch of C source file inputs. For each of those, the Zig compiler intentionally keeps hold of a shared advisory lock on the output file (well, technically on its cache manifest), and does not release it until the `Compilation` is destroyed, which only happens after we've completely finished emitting our archive. The advisory lock should be preventing any other Zig compiler process from trying to write the object file until we've finished building the archive. I did briefly audit the C object compilation logic for bugs, but barring a bug in `std.Build.Cache` itself, I couldn't spot any problems. Nonetheless, I still consider it likely that `ZigLLVMWriteArchive` is where the errors in #31520 are coming from. This patch---which fixes the unclean termination and actually reports LLVM's error properly---will help to test that hypothesis, and if it's correct, the improved error message will hopefully help to track down the underlying bug. --- src/codegen/llvm/bindings.zig | 2 ++ src/link/Lld.zig | 23 ++++++++++++++++++----- src/zig_llvm.cpp | 19 ++++++++++++++++--- src/zig_llvm.h | 7 ++++++- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index e4f4d6eafefcca250babb49e4a907eba22866d22..a312285db3310ba0fc69dffe55d56e484c293e50 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -331,6 +331,8 @@ extern fn ZigLLVMWriteArchive( file_names_ptr: [*]const [*:0]const u8, file_names_len: usize, archive_kind: ArchiveKind, + err_file_index_out: *usize, + err_msg_out: *[*:0]u8, ) bool; pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 04ffde350e146aa96a338a62aa953c51f501686f..cf64d3fd5bc51817cc86a7554ac65ee7aa53e373 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -269,12 +269,12 @@ pub fn flush( .wasm => wasmLink(lld, arena), }; result catch |err| switch (err) { - error.OutOfMemory, error.AlreadyReported => |e| return e, + error.OutOfMemory, error.AlreadyReported, error.Canceled => |e| return e, else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}), }; } -fn linkAsArchive(lld: *Lld, arena: Allocator) !void { +fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void { const base = &lld.base; const comp = base.comp; const directory = base.emit.root_dir; // Just an alias to make it shorter to type. @@ -338,7 +338,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { const llvm = @import("../codegen/llvm.zig"); const target = &comp.root_mod.resolved_target.result; llvm.initializeLLVMTarget(target.cpu.arch); - const bad = llvm_bindings.WriteArchive( + var err_file_index: usize = undefined; + var err_msg: [*:0]u8 = undefined; + if (llvm_bindings.WriteArchive( full_out_path_z, object_files.items.ptr, object_files.items.len, @@ -346,8 +348,19 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { .windows => .COFF, else => if (target.os.tag.isDarwin()) .DARWIN else .GNU, }, - ); - if (bad) return error.UnableToWriteArchive; + &err_file_index, + &err_msg, + )) { + defer std.c.free(err_msg); + if (err_file_index < object_files.items.len) { + return comp.link_diags.fail("LLD failed to open input file '{s}': {s}", .{ + object_files.items[err_file_index], + err_msg, + }); + } else { + return comp.link_diags.fail("LLD failed to write archive: {s}", .{err_msg}); + } + } } fn addCommonArgs(argv: *std.array_list.Managed([]const u8), coff: bool) !void { diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 9bba8e96d5107c6bf20ea2fd7f15e3df243d5bac..6b3ff4a5fbe626b37c0a49f7b734564c6563201e 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -473,19 +473,32 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { } bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, - ZigLLVMArchiveKind archive_kind) + ZigLLVMArchiveKind archive_kind, size_t *err_file_index_out, char **err_msg_out) { SmallVector new_members; for (size_t i = 0; i < file_name_count; i += 1) { Expected new_member = NewArchiveMember::getFile(file_names[i], true); Error err = new_member.takeError(); - if (err) return true; + if (err) { + *err_file_index_out = i; + const std::string msg = toString(std::move(err)); + *err_msg_out = (char *)malloc(msg.length() + 1); + strcpy(*err_msg_out, msg.c_str()); + return true; + } new_members.push_back(std::move(*new_member)); } Error err = writeArchive(archive_name, new_members, SymtabWritingMode::NormalSymtab, static_cast(archive_kind), true, false, nullptr); - if (err) return true; + if (err) { + *err_file_index_out = file_name_count; + const std::string msg = toString(std::move(err)); + *err_msg_out = (char *)malloc(msg.length() + 1); + strcpy(*err_msg_out, msg.c_str()); + return true; + } + return false; } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 64da388d477bfed46e0c4ae2e7da1cd16c73ce57..79ba0272df2f73743705ac832f5d508b5099542d 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -121,7 +121,12 @@ ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_earl ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output); ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output); +// On error, populates `*err_file_index_out` and `*err_msg_out` and returns `true`. The caller is +// responsible for freeing `*err_msg_out` using `free`. +// +// If an error occurs reading an input file, `*err_file_index_out` is set to the index of that input +// file in `file_names`. Otherwise, `*err_file_index_out` is set to `file_name_count`. ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, - ZigLLVMArchiveKind archive_kind); + ZigLLVMArchiveKind archive_kind, size_t *err_file_index_out, char **err_msg_out); #endif -- 2.54.0 From 0b681ec6c39bf49a590ce2a8fa46e91c08426c43 Mon Sep 17 00:00:00 2001 From: Techatrix Date: Mon, 13 Jul 2026 01:17:03 +0200 Subject: [PATCH 013/215] std.zig.Client: introduction --- lib/compiler/Maker/Step.zig | 18 ++-- lib/compiler/Maker/Step/Run.zig | 158 ++++++++------------------------ lib/compiler/std-docs.zig | 43 +++++---- lib/std/zig/Client.zig | 90 +++++++++++++++++- src/Compilation.zig | 20 ++-- tools/incr-check.zig | 64 +++++++------ 6 files changed, 202 insertions(+), 191 deletions(-) diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig index 812613928eaa9134dd249e4fc2ece38065cad01c..b8c5992cce243ed5b7f5fb0cdfc1b6b9d92f7fdb 100644 --- a/lib/compiler/Maker/Step.zig +++ b/lib/compiler/Maker/Step.zig @@ -561,24 +561,26 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi var result: ?Path = null; var eos_err: error{EndOfStream}!void = {}; - const stdout = zp.multi_reader.fileReader(0); + var client: std.zig.Client = .{ + .in = zp.multi_reader.reader(0), + .out = undefined, + }; while (true) { - const Header = std.zig.Server.Message.Header; - const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { - error.EndOfStream => break, - error.ReadFailed => return stdout.err.?, - }; - const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { + const header = client.receiveMessageWithMultiReader(&zp.multi_reader, .none) catch |err| switch (err) { + error.Timeout => unreachable, error.EndOfStream => |e| { + if (client.in.bufferedLen() == 0) break; // Better to report the crash with stderr below, but we set // this in case the child exits successfully while violating // this protocol. eos_err = e; break; }, - error.ReadFailed => return stdout.err.?, + else => |e| return e, }; + const body = client.in.take(header.bytes_len) catch unreachable; + switch (header.tag) { .zig_version => { if (!std.mem.eql(u8, builtin.zig_version_string, body)) { diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index b6fc911f01f8d25a27cf2f3829118accfe2f58ea..488225aadca8deb146e8fc1a2fd4c196c3811b2f 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -384,13 +384,23 @@ fn waitZigTest( var sub_prog_node: ?std.Progress.Node = null; defer if (sub_prog_node) |n| n.end(); + const stdout = multi_reader.reader(0); + const stderr = multi_reader.reader(1); + + var stdin_writer = child.stdin.?.writerStreaming(io, &.{}); + + var client: std.zig.Client = .{ + .in = stdout, + .out = &stdin_writer.interface, + }; + if (opt_metadata.*) |*md| { // Previous unit test process died or was killed; we're continuing where it left off - requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(&client, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; } else { // Running unit tests normally run.fuzz_tests.clearRetainingCapacity(); - sendMessage(io, child.stdin.?, .query_test_metadata) catch |err| return .{ .write_failed = err }; + client.serveBodylessMessage(.query_test_metadata) catch |err| return .{ .write_failed = err }; } var active_test_index: ?u32 = null; @@ -410,10 +420,6 @@ fn waitZigTest( .raw = .fromNanoseconds(ns), } else null; - const stdout = multi_reader.reader(0); - const stderr = multi_reader.reader(1); - const Header = std.zig.Server.Message.Header; - while (true) { const timeout: Io.Timeout = t: { const opt_duration = if (active_test_index == null) response_timeout else test_timeout; @@ -421,46 +427,20 @@ fn waitZigTest( break :t .{ .deadline = last_update.addDuration(duration) }; }; - // This block is exited when `stdout` contains enough bytes for a `Header`. - header_ready: { - if (stdout.buffered().len >= @sizeOf(Header)) { - // We already have one, no need to poll! - break :header_ready; - } - - multi_reader.fill(64, timeout) catch |err| switch (err) { - error.Timeout => return .{ .timeout = .{ - .active_test_index = active_test_index, - .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), - } }, - error.EndOfStream => return .{ .no_poll = .{ - .active_test_index = active_test_index, - .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), - } }, - else => |e| return e, - }; - - continue; - } - // There is definitely a header available now -- read it. - const header = stdout.takeStruct(Header, .little) catch unreachable; - - while (stdout.buffered().len < header.bytes_len) { - multi_reader.fill(64, timeout) catch |err| switch (err) { - error.Timeout => return .{ .timeout = .{ - .active_test_index = active_test_index, - .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), - } }, - error.EndOfStream => return .{ .no_poll = .{ - .active_test_index = active_test_index, - .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), - } }, - else => |e| return e, - }; - } - - const body = stdout.take(header.bytes_len) catch unreachable; + const header = client.receiveMessageWithMultiReader(multi_reader, timeout) catch |err| switch (err) { + error.Timeout => return .{ .timeout = .{ + .active_test_index = active_test_index, + .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), + } }, + error.EndOfStream => return .{ .no_poll = .{ + .active_test_index = active_test_index, + .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), + } }, + else => |e| return e, + }; + const body = client.in.take(header.bytes_len) catch unreachable; var body_r: std.Io.Reader = .fixed(body); + switch (header.tag) { .zig_version => { if (!std.mem.eql(u8, builtin.zig_version_string, body)) return step.fail( @@ -500,7 +480,7 @@ fn waitZigTest( active_test_index = null; last_update = .now(io, .awake); - requestNextTest(io, child.stdin.?, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(&client, &opt_metadata.*.?, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, .test_started => { active_test_index = opt_metadata.*.?.next_index - 1; @@ -551,7 +531,7 @@ fn waitZigTest( md.ns_per_test[tr_hdr.index] = @intCast(last_update.durationTo(now).raw.nanoseconds); last_update = now; - requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; + requestNextTest(&client, md, &sub_prog_node) catch |err| return .{ .write_failed = err }; }, else => {}, // ignore other messages } @@ -697,17 +677,18 @@ const FuzzTestRunner = struct { for (0.., f.instances) |id, *instance| { const id32: u32 = @intCast(id); + var writer = instance.child.stdin.?.writerStreaming(io, &.{}); + const client: std.zig.Client = .{ + .in = undefined, + .out = &writer.interface, + }; (switch (f.ctx.fuzz.mode) { - .forever => sendRunFuzzTestMessage( - io, - instance.child.stdin.?, + .forever => client.serveRunFuzzTestMessage( run.fuzz_tests.items, .forever, id32, ), - .limit => |limit| sendRunFuzzTestMessage( - io, - instance.child.stdin.?, + .limit => |limit| client.serveRunFuzzTestMessage( run.fuzz_tests.items, .iterations, limit.amount, @@ -1315,7 +1296,7 @@ pub const CachedTestMetadata = struct { } }; -fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { +fn requestNextTest(client: *std.zig.Client, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { while (metadata.next_index < metadata.names.len) { const i = metadata.next_index; metadata.next_index += 1; @@ -1326,76 +1307,11 @@ fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: if (sub_prog_node.*) |n| n.end(); sub_prog_node.* = metadata.prog_node.start(name, 0); - try sendRunTestMessage(io, in, .run_test, i); + try client.serveRunTest(i); return; } else { metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done - try sendMessage(io, in, .exit); - } -} - -fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { - const header: std.zig.Client.Message.Header = .{ - .tag = tag, - .bytes_len = 0, - }; - var w = file.writerStreaming(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; -} - -fn sendRunTestMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag, index: u32) !void { - const header: std.zig.Client.Message.Header = .{ - .tag = tag, - .bytes_len = 4, - }; - var w = file.writerStreaming(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - w.interface.writeInt(u32, index, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; -} - -fn sendRunFuzzTestMessage( - io: Io, - file: Io.File, - test_names: []const []const u8, - kind: std.Build.abi.fuzz.LimitKind, - amount_or_instance: u64, -) !void { - const header: std.zig.Client.Message.Header = .{ - .tag = .start_fuzzing, - .bytes_len = 1 + 8 + 4 + count: { - var c: u32 = @intCast(test_names.len * 4); - for (test_names) |name| { - c += @intCast(name.len); - } - break :count c; - }, - }; - var w = file.writerStreaming(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - w.interface.writeByte(@backingInt(kind)) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - w.interface.writeInt(u64, amount_or_instance, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - w.interface.writeInt(u32, @intCast(test_names.len), .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - for (test_names) |test_name| { - w.interface.writeInt(u32, @intCast(test_name.len), .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; - w.interface.writeAll(test_name) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; + try client.serveBodylessMessage(.exit); } } diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index f53123ae925a7fb4d997e1b8c1a5463624077780..0ed2c5bf186c2c91730b1aa4aa1755babdab0be2 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -346,29 +346,39 @@ fn buildWasmBinary( multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); defer multi_reader.deinit(); - try sendMessage(io, child.stdin.?, .update); - try sendMessage(io, child.stdin.?, .exit); + const stdout = multi_reader.reader(0); + + var stdin_buffer: [256]u8 = undefined; + var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer); + + var client: std.zig.Client = .{ + .in = stdout, + .out = &stdin_writer.interface, + }; + + try client.serveMessageHeader(.{ .tag = .update, .bytes_len = 0 }); + try client.serveMessageHeader(.{ .tag = .exit, .bytes_len = 0 }); + try client.out.flush(); var result: ?Cache.Path = null; var result_error_bundle = std.zig.ErrorBundle.empty; - const stdout = multi_reader.fileReader(0); - const MessageHeader = std.zig.Server.Message.Header; - var eos_err: error{EndOfStream}!void = {}; while (true) { - const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) { - error.EndOfStream => break, - error.ReadFailed => return stdout.err.?, - }; - const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { + const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Timeout => unreachable, error.EndOfStream => |e| { + if (client.in.bufferedLen() == 0) break; + // Better to report the crash with stderr below, but we set + // this in case the child exits successfully while violating + // this protocol. eos_err = e; break; }, - error.ReadFailed => return stdout.err.?, + else => |e| return e, }; + const body = client.in.take(header.bytes_len) catch unreachable; switch (header.tag) { .zig_version => { @@ -435,17 +445,6 @@ fn buildWasmBinary( }; } -fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { - const header: std.zig.Client.Message.Header = .{ - .tag = tag, - .bytes_len = 0, - }; - var w = file.writer(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { - error.WriteFailed => return w.err.?, - }; -} - fn openBrowserTab(io: Io, url: []const u8) !void { // Until https://github.com/ziglang/zig/issues/19205 is implemented, we // spawn and then leak a concurrent task for this child process. diff --git a/lib/std/zig/Client.zig b/lib/std/zig/Client.zig index fe50f2314a0b68b5bd9d6510efec6d4146477237..df4eb067bd7867ab5898cf1d27717b9bffd0a0ed 100644 --- a/lib/std/zig/Client.zig +++ b/lib/std/zig/Client.zig @@ -1,3 +1,17 @@ +const Client = @This(); + +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const OutMessage = std.zig.Client.Message; +const InMessage = std.zig.Server.Message; +const Reader = Io.Reader; +const Writer = Io.Writer; + +in: *Reader, +out: *Writer, + pub const Message = struct { pub const Header = extern struct { tag: Tag, @@ -50,7 +64,79 @@ pub const Message = struct { }; comptime { - const std = @import("std"); - std.debug.assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1); + assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1); } }; + +pub fn receiveMessage(c: *const Client) Reader.Error!InMessage.Header { + return c.in.takeStruct(InMessage.Header, .little); +} + +/// Assumes that `c.in` is a reader in `multi_reader`. +/// Guarantees that the response body will be buffered in `c.in` on success. +pub fn receiveMessageWithMultiReader( + c: *Client, + multi_reader: *Io.File.MultiReader, + timeout: Io.Timeout, +) (Io.File.MultiReader.Error || Io.Timeout.Error)!InMessage.Header { + while (c.in.bufferedLen() < @sizeOf(InMessage.Header)) { + multi_reader.fill(64, timeout) catch |err| switch (err) { + error.Canceled, + error.Timeout, + error.ConcurrencyUnavailable, + error.EndOfStream, + => |e| return e, + }; + } + const header = c.in.takeStruct(InMessage.Header, .little) catch unreachable; + while (c.in.bufferedLen() < header.bytes_len) { + try multi_reader.fill(header.bytes_len - c.in.bufferedLen(), timeout); + } + try multi_reader.checkAnyError(); + return header; +} + +/// Don't forget to flush! +pub fn serveMessageHeader(c: *const Client, header: OutMessage.Header) Writer.Error!void { + try c.out.writeStruct(header, .little); +} + +pub fn serveBodylessMessage(c: *const Client, tag: OutMessage.Tag) Writer.Error!void { + try c.serveMessageHeader(.{ .tag = tag, .bytes_len = 0 }); + try c.out.flush(); +} + +pub fn serveRunTest(c: *const Client, index: u32) !void { + try c.serveMessageHeader(.{ + .tag = .run_test, + .bytes_len = @sizeOf(u32), + }); + try c.out.writeInt(u32, index, .little); + try c.out.flush(); +} + +pub fn serveRunFuzzTestMessage( + c: *const Client, + test_names: []const []const u8, + kind: std.Build.abi.fuzz.LimitKind, + amount_or_instance: u64, +) !void { + try c.serveMessageHeader(.{ + .tag = .start_fuzzing, + .bytes_len = 1 + 8 + 4 + count: { + var bytes_len: u32 = @intCast(test_names.len * 4); + for (test_names) |name| { + bytes_len += @intCast(name.len); + } + break :count bytes_len; + }, + }); + try c.out.writeByte(@backingInt(kind)); + try c.out.writeInt(u64, amount_or_instance, .little); + try c.out.writeInt(u32, @intCast(test_names.len), .little); + for (test_names) |test_name| { + try c.out.writeInt(u32, @intCast(test_name.len), .little); + try c.out.writeAll(test_name); + } + try c.out.flush(); +} diff --git a/src/Compilation.zig b/src/Compilation.zig index 83b0f7ff2b206b23c947437fc514ca1c1cefed6a..bdb1d1a7de07b30cb03b21795f60b9f8b4bd654f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6006,26 +6006,30 @@ fn spawnZigRc( multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); defer multi_reader.deinit(); - const stdout = multi_reader.fileReader(0); - const MessageHeader = std.zig.Server.Message.Header; + const stdout = multi_reader.reader(0); var eos_err: error{EndOfStream}!void = {}; + var client: std.zig.Client = .{ + .in = stdout, + .out = undefined, + }; + while (true) { - const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) { - error.EndOfStream => break, - error.ReadFailed => return stdout.err.?, - }; - const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { + const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Timeout => unreachable, error.EndOfStream => |e| { + if (client.in.bufferedLen() == 0) break; // Better to report the crash with stderr below, but we set // this in case the child exits successfully while violating // this protocol. eos_err = e; break; }, - error.ReadFailed => return stdout.err.?, + else => |e| return e, }; + const body = client.in.take(header.bytes_len) catch unreachable; + switch (header.tag) { // We expect exactly one ErrorBundle, and if any error_bundle header is // sent then it's a fatal error. diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 89c14ce1e7f60a710e863349025d3803f2dc37bb..cbc1ec659409eadefd89d516c8816ed36f92d4e5 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -305,21 +305,23 @@ const Eval = struct { fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void { const arena = eval.arena; - const stdout = mr.fileReader(0); - const stderr = &mr.fileReader(1).interface; - const Header = std.zig.Server.Message.Header; + const stdout = mr.reader(0); + const stderr = mr.reader(1); + + var client: std.zig.Client = .{ + .in = stdout, + .out = undefined, + }; while (true) { - const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { - error.EndOfStream => break, - error.ReadFailed => return stdout.err.?, - }; - const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { + const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { + error.Timeout => unreachable, // If this panic triggers it might be helpful to rework this // code to print the stderr from the abnormally terminated child. error.EndOfStream => @panic("unexpected mid-message end of stream"), - error.ReadFailed => return stdout.err.?, + else => |e| return e, }; + const body = client.in.take(header.bytes_len) catch unreachable; switch (header.tag) { .error_bundle => { @@ -605,12 +607,13 @@ const Eval = struct { fn requestUpdate(eval: *Eval) !void { const io = eval.io; - const header: std.zig.Client.Message.Header = .{ - .tag = .update, - .bytes_len = 0, + + var w = eval.child.stdin.?.writerStreaming(io, &.{}); + var client: std.zig.Client = .{ + .in = undefined, + .out = &w.interface, }; - var w = eval.child.stdin.?.writer(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { + client.serveBodylessMessage(.update) catch |err| switch (err) { error.WriteFailed => return w.err.?, }; } @@ -618,22 +621,23 @@ const Eval = struct { fn end(eval: *Eval, mr: *Io.File.MultiReader) !void { requestExit(eval.child, eval); - const stdout = mr.fileReader(0); - const Header = std.zig.Server.Message.Header; + var client: std.zig.Client = .{ + .in = mr.reader(0), + .out = undefined, + }; while (true) { - const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { - error.EndOfStream => break, - error.ReadFailed => return stdout.err.?, - }; - stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) { - error.ReadFailed => return stdout.err.?, - error.EndOfStream => |e| return e, + const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { + error.Timeout => unreachable, + error.EndOfStream => |e| { + if (client.in.bufferedLen() == 0) break; + return e; + }, + else => |e| return e, }; + try client.in.discardAll(header.bytes_len); } - try mr.fillRemaining(.none); - const stderr = mr.reader(1).buffered(); if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr}); } @@ -899,12 +903,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void { if (child.stdin == null) return; const io = eval.io; - const header: std.zig.Client.Message.Header = .{ - .tag = .exit, - .bytes_len = 0, + var w = eval.child.stdin.?.writerStreaming(io, &.{}); + var client: std.zig.Client = .{ + .in = undefined, + .out = &w.interface, }; - var w = eval.child.stdin.?.writer(io, &.{}); - w.interface.writeStruct(header, .little) catch |err| switch (err) { + client.serveBodylessMessage(.exit) catch |err| switch (err) { error.WriteFailed => switch (w.err.?) { error.BrokenPipe => {}, else => |e| eval.fatal("failed to send exit: {t}", .{e}), -- 2.54.0 From fb6ab7f5646c03e867cd76208be36d82f4e38df7 Mon Sep 17 00:00:00 2001 From: Techatrix Date: Sun, 12 Jul 2026 23:46:20 +0200 Subject: [PATCH 014/215] std.zig.buildExeSubprocess: use multireader --- lib/std/zig.zig | 100 +++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 4c41d56845f7ebd32bb83a51d2ec182b7e4e7154..e250a751a0337ad8a7ceca93bbab11a65c997cf4 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -1658,31 +1658,32 @@ pub fn buildExeSubprocess( }; defer child.kill(io); - var stderr_task = io.concurrent(readStreamAlloc, .{ gpa, io, child.stderr.?, .unlimited }) catch - @panic("TODO use multireader instead"); - defer if (stderr_task.cancel(io)) |slice| gpa.free(slice) else |_| {}; + var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; + var multi_reader: Io.File.MultiReader = undefined; + multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); + defer multi_reader.deinit(); + const stdout = multi_reader.reader(0); + const stderr = multi_reader.reader(1); - var stdout_buffer: [512]u8 = undefined; - var stdout_reader: Io.File.Reader = .initStreaming(child.stdout.?, io, &stdout_buffer); - const stdout = &stdout_reader.interface; + var stdin_buffer: [8]u8 = undefined; + var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer); - { - var w = child.stdin.?.writer(io, &.{}); - w.interface.writeStruct(Client.Message.Header{ .tag = .update, .bytes_len = 0 }, .little) catch |err| switch (err) { - error.WriteFailed => { - log.err("{t} writing to command: {f}", .{ w.err.?, cmd }); - return error.AlreadyReported; - }, - }; - w.interface.writeStruct(Client.Message.Header{ .tag = .exit, .bytes_len = 0 }, .little) catch |err| switch (err) { - error.WriteFailed => { - log.err("{t} writing to command: {f}", .{ w.err.?, cmd }); - return error.AlreadyReported; - }, - }; - } + var client: Client = .{ + .in = stdout, + .out = &stdin_writer.interface, + }; - const Header = Server.Message.Header; + (blk: { + client.serveMessageHeader(.{ .tag = .update, .bytes_len = 0 }) catch |err| break :blk err; + client.serveMessageHeader(.{ .tag = .exit, .bytes_len = 0 }) catch |err| break :blk err; + client.out.flush() catch |err| break :blk err; + }) catch |err| switch (err) { + error.WriteFailed => { + if (stdin_writer.err.? == error.Canceled) return error.Canceled; + log.err("{t} writing to command: {f}", .{ stdin_writer.err.?, cmd }); + return error.AlreadyReported; + }, + }; var result: ?Cache.Path = null; defer if (result) |r| gpa.free(r.sub_path); @@ -1690,33 +1691,29 @@ pub fn buildExeSubprocess( var result_error_bundle: ErrorBundle = .empty; defer result_error_bundle.deinit(gpa); - var body_buffer: std.ArrayList(u8) = .empty; - defer body_buffer.deinit(gpa); - var received_fs_inputs = false; var cache_hit = false; + var eos_err: error{EndOfStream}!void = {}; + while (true) { - const header = stdout.takeStruct(Header, .little) catch |err| switch (err) { - error.ReadFailed => { - log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd }); - return error.AlreadyReported; - }, - error.EndOfStream => break, - }; - body_buffer.clearRetainingCapacity(); - stdout.appendExact(gpa, &body_buffer, header.bytes_len) catch |err| switch (err) { - error.ReadFailed => { - log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd }); - return error.AlreadyReported; + const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Timeout => unreachable, + error.EndOfStream => |e| { + if (client.in.bufferedLen() == 0) break; + // Better to report the crash with stderr below, but we set + // this in case the child exits successfully while violating + // this protocol. + eos_err = e; + break; }, - error.OutOfMemory => |e| return e, - error.EndOfStream => { - log.err("unexpected end of stream from command: {f}", .{cmd}); + error.Canceled, error.OutOfMemory => |e| return e, + else => |e| { + log.err("{t} reading from command: {f}", .{ e, cmd }); return error.AlreadyReported; }, }; - const body = body_buffer.items; + const body = stdout.take(header.bytes_len) catch unreachable; switch (header.tag) { .zig_version => { @@ -1767,16 +1764,15 @@ pub fn buildExeSubprocess( } } - const stderr_contents = stderr_task.await(io) catch |err| switch (err) { - error.Canceled, error.OutOfMemory => |e| return e, - else => |e| c: { - log.warn("{t} reading stderr from command: {f}", .{ e, cmd }); - break :c ""; - }, - }; + const stderr_contents = stderr.buffered(); if (stderr_contents.len > 0) log.warn("unexpected stderr from {s} command:\n{s}", .{ options.argv[0], stderr_contents }); + eos_err catch { + log.err("unexpected end of stream from command: {f}", .{cmd}); + return error.AlreadyReported; + }; + // Send EOF to stdin. child.stdin.?.close(io); child.stdin = null; @@ -1834,14 +1830,6 @@ pub fn buildExeSubprocess( }; } -fn readStreamAlloc(gpa: Allocator, io: Io, file: Io.File, limit: Io.Limit) ![]u8 { - var file_reader: Io.File.Reader = .initStreaming(file, io, &.{}); - return file_reader.interface.allocRemaining(gpa, limit) catch |err| switch (err) { - error.ReadFailed => return file_reader.err.?, - else => |e| return e, - }; -} - test { _ = Ast; _ = AstRlAnnotate; -- 2.54.0 From bb17211958a236e592043895bdfba317c6e7cd16 Mon Sep 17 00:00:00 2001 From: Techatrix Date: Fri, 10 Jul 2026 21:05:26 +0200 Subject: [PATCH 015/215] std.zig.Server: remove init function The `.zig_version` message will not be used by the build system protocol. --- lib/compiler/objcopy.zig | 6 +++--- lib/compiler/test_runner.zig | 6 +++--- lib/std/zig/Server.zig | 19 ------------------- src/main.zig | 7 ++----- 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 857299a60e16f410c3eb54ca6be8382c33b99567..3e6967779598067003281d655f07c519def94340 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -214,11 +214,11 @@ fn cmdObjCopy(arena: Allocator, io: Io, args: []const []const u8) !void { if (listen) { var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); - var server = try Server.init(.{ + var server: Server = .{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, - .zig_version = builtin.zig_version_string, - }); + }; + try server.serveStringMessage(.zig_version, builtin.zig_version_string); var seen_update = false; while (true) { diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 62c09fe22800abc8aeb462dbd8c8beffe0ef7925..8cbd4aa75787c3566f7f77516069021d10b7c6e5 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -78,11 +78,11 @@ fn mainServer(init: std.process.Init.Minimal) !void { @disableInstrumentation(); stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer); stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer); - var server = try std.zig.Server.init(.{ + var server: std.zig.Server = .{ .in = &stdin_reader.interface, .out = &stdout_writer.interface, - .zig_version = builtin.zig_version_string, - }); + }; + try server.serveStringMessage(.zig_version, builtin.zig_version_string); while (true) { const hdr = try server.receiveMessage(); diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index cf43cb0af2822cf416868dd1eba76bcb06b791a7..5c1cb20b36c713a1dad9353833d67037626739e6 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -1,12 +1,8 @@ const Server = @This(); -const builtin = @import("builtin"); - const std = @import("std"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const native_endian = builtin.target.cpu.arch.endian(); -const need_bswap = native_endian != .little; const Cache = std.Build.Cache; const OutMessage = std.zig.Server.Message; const InMessage = std.zig.Client.Message; @@ -140,21 +136,6 @@ pub const Message = struct { }; }; -pub const Options = struct { - in: *Reader, - out: *Writer, - zig_version: []const u8, -}; - -pub fn init(options: Options) !Server { - var s: Server = .{ - .in = options.in, - .out = options.out, - }; - try s.serveStringMessage(.zig_version, options.zig_version); - return s; -} - pub fn receiveMessage(s: *Server) !InMessage.Header { return s.in.takeStruct(InMessage.Header, .little); } diff --git a/src/main.zig b/src/main.zig index 94011c81f9215df1da00328f221c41e42b9bc214..9326501f650e29ba38a285aeb8964819fe4cef23 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4305,11 +4305,8 @@ fn serve( const gpa = comp.gpa; const io = comp.io; - var server = try Server.init(.{ - .in = in, - .out = out, - .zig_version = build_options.version, - }); + var server: Server = .{ .in = in, .out = out }; + try server.serveStringMessage(.zig_version, build_options.version); var child_pid: ?std.process.Child.Id = null; -- 2.54.0 From f58c93b5663beacb71dc7add21a85bd0b4f4dc46 Mon Sep 17 00:00:00 2001 From: Techatrix Date: Tue, 21 Jul 2026 16:31:04 +0200 Subject: [PATCH 016/215] Maker: implement build system protocol foundation --- lib/compiler/Maker.zig | 103 +++++++++++++++++++- lib/std/zig/Server.zig | 30 ++++++ test/standalone/build.zig | 1 + tools/bsp.zig | 196 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 tools/bsp.zig diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index b5db0e68f7597a1e951900e8b741afb20521bcda..e692343bd2a8e1e052b0b536d7bf03d5f03fa054 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -11,6 +11,7 @@ const File = std.Io.File; const Io = std.Io; const Dir = std.Io.Dir; const Path = std.Build.Cache.Path; +const Reader = std.Io.Reader; const Writer = std.Io.Writer; const assert = std.debug.assert; const fatal = std.process.fatal; @@ -19,6 +20,8 @@ const log = std.log; const mem = std.mem; const process = std.process; const Color = std.zig.Color; +const Client = std.zig.Client; +const Server = std.zig.Server; const EnvVar = std.zig.EnvVar; const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename; const stringToEnum = std.meta.stringToEnum; @@ -51,6 +54,8 @@ max_rss_mutex: Io.Mutex, skip_oom_steps: bool, unit_test_timeout_ns: ?u64, watch: bool, +protocol_server: ?*AvoidableServer, +protocol_server_mutex: Io.Mutex, web_server: ?*AvoidableWebServer, /// Allocated into `gpa`. memory_blocked_steps: std.ArrayList(Configuration.Step.Index), @@ -67,6 +72,7 @@ var stdio_buffer_allocation: [256]u8 = undefined; var stdout_writer_allocation: Io.File.Writer = undefined; var debug_maker_leaks: bool = false; +const AvoidableServer = if (builtin.single_threaded) void else Server; const AvoidableWebServer = if (builtin.single_threaded) void else WebServer; const is_debug_mode = builtin.mode == .debug; @@ -216,6 +222,7 @@ pub fn main(init: process.Init.Minimal) !void { var watch = false; var fuzz: ?Fuzz.Mode = null; var debounce_interval_ms: u16 = 50; + var listen: bool = false; var webui_listen: ?Io.net.IpAddress = null; var debug_pkg_config = false; var run_args: ?[]const []const u8 = null; @@ -416,6 +423,8 @@ pub fn main(init: process.Init.Minimal) !void { next_arg, err, }); }; + } else if (mem.eql(u8, arg, "--listen=-")) { + listen = true; } else if (mem.eql(u8, arg, "--webui")) { if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) }; } else if (mem.startsWith(u8, arg, "--webui=")) { @@ -553,7 +562,7 @@ pub fn main(init: process.Init.Minimal) !void { } const early_exit_mode = fetch_only or help_menu or steps_menu or print_configuration != .none; - const server_mode = !early_exit_mode and (watch or webui_listen != null or fuzz != null); + const server_mode = !early_exit_mode and (watch or webui_listen != null or fuzz != null or listen); process.raiseFileDescriptorLimit(); @@ -661,6 +670,25 @@ pub fn main(init: process.Init.Minimal) !void { break :ws &web_server_allocation; } else null; + var stdin_buffer: [256]u8 = undefined; + var stdout_buffer: [256]u8 = undefined; + var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); + var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); + + var protocol_server_allocation: AvoidableServer = undefined; + const protocol_server: ?*AvoidableServer = if (listen) s: { + if (builtin.single_threaded) fatal("--listen is not yet supported on single-threaded hosts", .{}); + if (watch) fatal("using '--watch' and '--listen' together is not supported", .{}); + if (fuzz != null) fatal("using '--fuzz' and '--listen' together is not supported", .{}); + if (step_names.items.len > 0) fatal("build steps must be provided over the protocol instead of using CLI arguments", .{}); + protocol_server_allocation = .{ + .in = &stdin_reader.interface, + .out = &stdout_writer.interface, + }; + try serveBSPHandshake(&protocol_server_allocation); + break :s &protocol_server_allocation; + } else null; + while (true) { // If this fails, we can still start the server and wait for user // to request a rebuild. If it returns error.FailedButCacheIntact @@ -731,13 +759,20 @@ pub fn main(init: process.Init.Minimal) !void { .watch = watch, .web_server = web_server, + .protocol_server = protocol_server, + .protocol_server_mutex = .init, .memory_blocked_steps = .empty, .step_stack = .empty, .pkg_config = .{ .debug = debug_pkg_config }, .error_style = error_style, .multiline_errors = multiline_errors, - .summary = summary orelse if (watch or webui_listen != null) .new else .failures, + .summary = summary orelse if (listen) + .none + else if (watch or webui_listen != null) + .new + else + .failures, }; defer { maker.memory_blocked_steps.deinit(gpa); @@ -749,6 +784,52 @@ pub fn main(init: process.Init.Minimal) !void { maker.max_rss_is_default = true; } + if (protocol_server) |s| { + try s.serveStringMessage(.bsp_configuration, try arena.print("{f}", .{scanned_config.path})); + + var w: ?Watch = null; + + const Event = union(enum) { + message: Reader.Error!Client.Message.Header, + fs_event: if (Watch.have_impl) @typeInfo(@TypeOf(Watch.wait)).@"fn".return_type.? else noreturn, + }; + + var select_buffer: [2]Event = undefined; + var select: Io.Select(Event) = .init(io, &select_buffer); + defer select.cancelDiscard(); + + try select.concurrent(.message, Server.receiveMessage, .{s}); + + var in_debounce = false; + loop: switch (try select.await()) { + .message => |payload| { + const header: Client.Message.Header = try payload; + switch (header.tag) { + .exit => { + cleanExit(io, &scanned_config); + process.exit(0); + }, + else => fatal("unsupported message: {t}", .{header.tag}), + } + }, + .fs_event => |payload| { + if (!Watch.have_impl) unreachable; + switch (try payload) { + .timeout => { + assert(in_debounce); + markFailedStepsDirty(&maker); + if (true) @panic("TODO run steps that were previous specified over the build system protocol"); + in_debounce = false; + }, + .dirty => in_debounce = true, + .clean => {}, + } + try select.concurrent(.fs_event, Watch.wait, .{ &w.?, if (in_debounce) .{ .ms = debounce_interval_ms } else .none }); + continue :loop try select.await(); + }, + } + } + maker.prepare(step_names.items) catch |err| switch (err) { error.DependencyLoopDetected, error.InsufficientMemory => { // TODO handle DependencyLoopDetected as error.FailedButCacheIntact @@ -850,6 +931,9 @@ pub fn main(init: process.Init.Minimal) !void { _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; process.exit(1); } + if (protocol_server != null) { + fatal("(zig build system) TODO send error messages to client when build.zig compilation fails", .{}); + } if (watch and can_fs_watch) { fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{}); } else { @@ -2990,6 +3074,21 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void { } } +fn serveBSPHandshake(s: *const std.zig.Server) !void { + const handshake_header: Server.Message.Handshake = .{ + .version = Server.build_system_version, + .flags = .{ + .file_system_watch_supported = Watch.have_impl, + }, + }; + try s.serveMessageHeader(.{ + .tag = .bsp_handshake, + .bytes_len = @sizeOf(Server.Message.Handshake), + }); + try s.out.writeStruct(handshake_header, .little); + try s.out.flush(); +} + fn initStdoutWriter(io: Io) *Writer { stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); return &stdout_writer_allocation.interface; diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index 5c1cb20b36c713a1dad9353833d67037626739e6..1da63f95310b561f4264771a271fe70346c82fe7 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -12,6 +12,14 @@ const Writer = std.Io.Writer; in: *Reader, out: *Writer, +/// The ABI version of the build system protocol. Will be bumped whenever a +/// backwards incompatible changes to the protocol is made. +/// +/// Does not apply to the internal compiler protocol or test runner. +/// +/// See `version` in `Message.Handshake`. +pub const build_system_version: u32 = 1; + pub const Message = struct { pub const Header = extern struct { tag: Tag, @@ -66,9 +74,31 @@ pub const Message = struct { /// Body is a TimeReport. time_report, + /// The first message sent by the server over the build system protocol. + /// Body is a `Handshake`. + /// This message only applies to the build system protocol. + bsp_handshake = 0x80000000, + /// Notifies that a new configuration file is available. + /// Body is a cwd relative path to the configuration file. + /// This message only applies to the build system protocol. + bsp_configuration, + _, }; + /// Trailing: + /// * base_paths: BasePaths, + pub const Handshake = extern struct { + /// See `build_system_version`. + version: u32, + flags: Flags, + + pub const Flags = packed struct(u32) { + file_system_watch_supported: bool, + _: u31 = 0, + }; + }; + pub const PathPrefix = enum(u8) { cwd, zig_lib, diff --git a/test/standalone/build.zig b/test/standalone/build.zig index dc8d85d399477256b65c60dc1b4850144c641738..1679c32af85839baa16a7305ea53b22aacc75149 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void { const tools_target = b.resolveTargetQuery(.{}); for ([_][]const u8{ // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`. + "../../tools/bsp.zig", "../../tools/check_mingw.zig", "../../tools/dump-cov.zig", "../../tools/fetch_them_macos_headers.zig", diff --git a/tools/bsp.zig b/tools/bsp.zig new file mode 100644 index 0000000000000000000000000000000000000000..875fda3e772739f6c337355027c84784e8e9a2d3 --- /dev/null +++ b/tools/bsp.zig @@ -0,0 +1,196 @@ +//! CLI tool to interface with the build system protocol (zig build --listen=-) + +const std = @import("std"); +const Io = std.Io; +const Allocator = std.mem.Allocator; +const Configuration = std.Build.Configuration; +const Client = std.zig.Client; +const Server = std.zig.Server; +const log = std.log.scoped(.bsp); + +pub fn main(init: std.process.Init) !void { + const io = init.io; + const gpa = init.gpa; + const arena = init.arena.allocator(); + + var maker_args: std.ArrayList([]const u8) = .empty; + + const args = try init.minimal.args.toSlice(arena); + for (args[1..]) |arg| { + try maker_args.append(arena, try arena.dupe(u8, arg)); + } + if (maker_args.items.len < 1) try maker_args.append(arena, "zig"); + if (maker_args.items.len < 2) try maker_args.append(arena, "build"); + if (!std.mem.eql(u8, maker_args.last().?.*, "--listen=-")) try maker_args.append(arena, "--listen=-"); + + log.debug("cmd: {f}", .{std.zig.SubprocessCommand{ + .argv = maker_args.items, + }}); + + var child_process = std.process.spawn(io, .{ + .argv = maker_args.items, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + }) catch |err| std.debug.panic("failed to spawn process: {}", .{err}); + errdefer child_process.kill(io); + + var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; + var multi_reader: Io.File.MultiReader = undefined; + defer multi_reader.deinit(); + multi_reader.init( + gpa, + io, + multi_reader_buffer.toStreams(), + &.{ child_process.stdout.?, child_process.stderr.? }, + ); + const client_stdout = multi_reader.reader(0); + const client_stderr = multi_reader.reader(1); + + var client_stdout_buffer: [256]u8 = undefined; + var client_stdout_writer = child_process.stdin.?.writerStreaming(io, &client_stdout_buffer); + + var client: Client = .{ + .in = client_stdout, + .out = &client_stdout_writer.interface, + }; + + const err = blk: { + const handshake: Server.Message.Handshake = handshake: { + const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Canceled, error.ConcurrencyUnavailable => |e| return e, + error.Timeout => unreachable, + else => |e| { + log.err("failed to receive message: {t}", .{err}); + break :blk e; + }, + }; + const body = client_stdout.take(header.bytes_len) catch unreachable; + log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len }); + + if (header.tag != .bsp_handshake) { + log.err("received unexpected message: {f}", .{fmtEnum(header.tag)}); + return error.UnexpectedMessage; + } + + var r: Io.Reader = .fixed(body); + break :handshake try r.takeStruct(Server.Message.Handshake, .little); + }; + _ = handshake; + + var conf_arena_allocator: std.heap.ArenaAllocator = .init(gpa); + defer conf_arena_allocator.deinit(); + const conf_arena = conf_arena_allocator.allocator(); + + const configuration = configuration: { + const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Canceled, error.ConcurrencyUnavailable => |e| return e, + error.Timeout => unreachable, + else => |e| { + log.err("failed to receive message: {t}", .{err}); + break :blk e; + }, + }; + const body = client_stdout.take(header.bytes_len) catch unreachable; + log.debug("received {t} ({d} bytes)", .{ header.tag, body.len }); + + if (header.tag != .bsp_configuration) { + log.err("received unexpected message: {f}", .{fmtEnum(header.tag)}); + return error.UnexpectedMessage; + } + + const configuration_path = body; + var file = Io.Dir.cwd().openFile(io, configuration_path, .{}) catch |err| + std.debug.panic("failed to open configuration file {q}: {t}", .{ configuration_path, err }); + defer file.close(io); + break :configuration Configuration.loadFile(conf_arena, io, file) catch |err| + std.debug.panic("failed to load configuration file {q}: {t}", .{ configuration_path, err }); + }; + const c = &configuration; + + var top_level_steps: std.array_hash_map.String(Configuration.Step.Index) = .empty; + defer top_level_steps.deinit(gpa); + + for (c.steps, 0..) |*conf_step, step_index_usize| { + if (conf_step.owner != .root) continue; + const step_index: Configuration.Step.Index = @fromBackingInt(@intCast(step_index_usize)); + const flags = conf_step.flags(c); + if (flags.tag != .top_level) continue; + const name = step_index.ptr(c).name.slice(c); + try top_level_steps.putNoClobber(gpa, name, step_index); + } + + std.debug.print("Steps:\n", .{}); + for (top_level_steps.keys()) |name| { + std.debug.print(" - {q}\n", .{name}); + } + std.debug.print( + \\Available Commands: + \\ - build [step names / step indices] + \\ - watch [step names / step indices] + \\ - exit + \\ + , .{}); + + var stdin_reader_buffer: [256]u8 = undefined; + var stdin_reader = Io.File.stdin().reader(io, &stdin_reader_buffer); + const stdin = &stdin_reader.interface; + + while (true) { + try Io.File.stdout().writeStreamingAll(io, "> "); + const command = try stdin.takeDelimiterExclusive('\n'); + stdin.toss(1); + if (std.mem.startsWith(u8, command, "build") or + std.mem.startsWith(u8, command, "watch")) + { + @panic("TODO"); + } else if (std.mem.eql(u8, command, "exit")) { + try client.serveBodylessMessage(.exit); + break; + } else { + log.err("unknown command: {q}", .{command}); + continue; + } + } + }; + + try multi_reader.fillRemaining(.none); + + if (client_stderr.bufferedLen() > 0) { + log.err("stderr:\n{s}\n", .{client_stderr.buffered()}); + } + + try err; + + const term = try child_process.wait(io); + + if (!term.success()) { + log.err("maker {f}", .{term}); + } +} + +const FormatEnum = union(enum) { + named: []const u8, + unnamed: usize, + + pub fn format( + e: FormatEnum, + writer: *std.Io.Writer, + ) std.Io.Writer.Error!void { + switch (e) { + .named => |name| { + try writer.writeByte('.'); + try writer.writeAll(name); + }, + .unnamed => |number| try writer.print("0x{x}", .{number}), + } + } +}; + +fn fmtEnum(e: anytype) FormatEnum { + if (std.enums.tagName(@TypeOf(e), e)) |name| { + return .{ .named = name }; + } else { + return .{ .unnamed = @backingInt(e) }; + } +} -- 2.54.0 From 54162b1b9d1df526a145d6c825de3640dee50ede Mon Sep 17 00:00:00 2001 From: Techatrix Date: Tue, 21 Jul 2026 16:31:29 +0200 Subject: [PATCH 017/215] Maker: implement build steps request --- lib/compiler/Maker.zig | 111 ++++++++++++++++++++++++++++++++--------- lib/std/zig/Client.zig | 38 ++++++++++++++ tools/bsp.zig | 27 +++++++++- 3 files changed, 151 insertions(+), 25 deletions(-) diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index e692343bd2a8e1e052b0b536d7bf03d5f03fa054..61e815370fd9952163dfd9f2f0f29afb3380791d 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -60,6 +60,8 @@ web_server: ?*AvoidableWebServer, /// Allocated into `gpa`. memory_blocked_steps: std.ArrayList(Configuration.Step.Index), /// Allocated into `gpa`. +initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void), +/// Allocated into `gpa`. step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void), pkg_config: PkgConfig, @@ -762,6 +764,7 @@ pub fn main(init: process.Init.Minimal) !void { .protocol_server = protocol_server, .protocol_server_mutex = .init, .memory_blocked_steps = .empty, + .initial_steps = .empty, .step_stack = .empty, .pkg_config = .{ .debug = debug_pkg_config }, @@ -776,6 +779,7 @@ pub fn main(init: process.Init.Minimal) !void { }; defer { maker.memory_blocked_steps.deinit(gpa); + maker.initial_steps.deinit(gpa); maker.step_stack.deinit(gpa); } @@ -809,6 +813,41 @@ pub fn main(init: process.Init.Minimal) !void { cleanExit(io, &scanned_config); process.exit(0); }, + .bsp_build_steps => { + // Cancel existing file watching + select.cancelDiscard(); + in_debounce = false; + + const body = try s.in.takeStruct(Client.Message.BuildSteps, .little); + const steps = try s.in.readSliceEndianAlloc(gpa, Configuration.Step.Index, body.step_count, .little); + defer gpa.free(steps); + if (body.flags.watch and !Watch.have_impl) fatal("file watching is unavailable", .{}); + + try select.concurrent(.message, Server.receiveMessage, .{s}); + + maker.watch = body.flags.watch; + maker.prepare(steps) catch |err| switch (err) { + error.DependencyLoopDetected, error.InsufficientMemory => { + // TODO handle DependencyLoopDetected as error.FailedButCacheIntact + // and handle InsufficientMemory as error.AlreadyReported + _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; + process.exit(1); + }, + else => |e| return e, + }; + + try maker.makeSteps(main_progress_node, null); + + if (body.flags.watch) { + if (!Watch.have_impl) unreachable; + if (w == null) w = try .init(&maker); + + try w.?.update(maker.step_stack.keys()); + try select.concurrent(.fs_event, Watch.wait, .{ &w.?, if (in_debounce) .{ .ms = debounce_interval_ms } else .none }); + } + + continue :loop try select.await(); + }, else => fatal("unsupported message: {t}", .{header.tag}), } }, @@ -818,7 +857,7 @@ pub fn main(init: process.Init.Minimal) !void { .timeout => { assert(in_debounce); markFailedStepsDirty(&maker); - if (true) @panic("TODO run steps that were previous specified over the build system protocol"); + try maker.makeSteps(main_progress_node, null); in_debounce = false; }, .dirty => in_debounce = true, @@ -830,7 +869,10 @@ pub fn main(init: process.Init.Minimal) !void { } } - maker.prepare(step_names.items) catch |err| switch (err) { + const initial_steps = try maker.resolveTopLevelSteps(step_names.items); + defer gpa.free(initial_steps); + + maker.prepare(initial_steps) catch |err| switch (err) { error.DependencyLoopDetected, error.InsufficientMemory => { // TODO handle DependencyLoopDetected as error.FailedButCacheIntact // and handle InsufficientMemory as error.AlreadyReported @@ -857,7 +899,7 @@ pub fn main(init: process.Init.Minimal) !void { }) { if (web_server) |ws| ws.startBuild(); - try maker.makeStepNames(step_names.items, main_progress_node, fuzz); + try maker.makeSteps(main_progress_node, fuzz); if (web_server) |ws| { if (fuzz) |mode| if (mode != .forever) fatal( @@ -2104,11 +2146,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { return &maker.steps[@backingInt(i)]; } -fn prepare(maker: *Maker, step_names: []const []const u8) !void { +fn resolveTopLevelSteps(maker: *Maker, step_names: []const []const u8) ![]const Configuration.Step.Index { + const gpa = maker.gpa; + const c = &maker.scanned_config.configuration; + + if (step_names.len == 0) { + return try gpa.dupe(Configuration.Step.Index, &.{c.default_step}); + } + + var result: std.array_hash_map.Auto(Configuration.Step.Index, void) = .empty; + defer result.deinit(gpa); + + try result.ensureTotalCapacity(gpa, step_names.len); + + for (0..step_names.len) |i| { + const step_name = step_names[step_names.len - i - 1]; + const s = maker.scanned_config.top_level_steps.get(step_name) orelse { + log.info("to list available steps: zig build -l", .{}); + fatal("no such step: {s}", .{step_name}); + }; + result.putAssumeCapacity(s, {}); + } + + return try gpa.dupe(Configuration.Step.Index, result.keys()); +} + +fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void { const gpa = maker.gpa; const graph = maker.graph; const arena = graph.arena; const seed: u32 = graph.random_seed; + const initial_steps = &maker.initial_steps; const step_stack = &maker.step_stack; const c = &maker.scanned_config.configuration; @@ -2117,18 +2185,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) }; } - if (step_names.len == 0) { - try step_stack.put(gpa, c.default_step, {}); - } else { - try step_stack.ensureUnusedCapacity(gpa, step_names.len); - for (0..step_names.len) |i| { - const step_name = step_names[step_names.len - i - 1]; - const s = maker.scanned_config.top_level_steps.get(step_name) orelse { - log.info("to list available steps: zig build -l", .{}); - fatal("no such step: {s}", .{step_name}); - }; - step_stack.putAssumeCapacity(s, {}); - } + try initial_steps.ensureUnusedCapacity(gpa, step_indices.len); + try step_stack.ensureUnusedCapacity(gpa, step_indices.len); + + initial_steps.clearRetainingCapacity(); + step_stack.clearRetainingCapacity(); + + for (step_indices) |step| { + initial_steps.putAssumeCapacity(step, {}); + step_stack.putAssumeCapacity(step, {}); } const starting_steps = try arena.dupe(Configuration.Step.Index, step_stack.keys()); @@ -2177,9 +2242,8 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { } } -fn makeStepNames( +fn makeSteps( maker: *Maker, - step_names: []const []const u8, parent_progress_node: std.Progress.Node, fuzz: ?Fuzz.Mode, ) !void { @@ -2367,7 +2431,7 @@ fn makeStepNames( defer step_stack_copy.deinit(gpa); var print_node: PrintNode = .{ .parent = null }; - if (step_names.len == 0) { + if (maker.initial_steps.count() == 0) { print_node.last = true; printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) { error.Canceled => |e| return e, @@ -2375,10 +2439,10 @@ fn makeStepNames( }; } else { const last_index = if (maker.summary == .all) top_level_steps.count() else blk: { - var i: usize = step_names.len; + var i: usize = maker.initial_steps.count(); while (i > 0) { i -= 1; - const step_index = top_level_steps.get(step_names[i]).?; + const step_index = maker.initial_steps.keys()[i]; const step = maker.stepByIndex(step_index); const found = switch (maker.summary) { .all, .line, .none => unreachable, @@ -2389,8 +2453,7 @@ fn makeStepNames( } break :blk top_level_steps.count(); }; - for (step_names, 0..) |step_name, i| { - const step_index = top_level_steps.get(step_name).?; + for (maker.initial_steps.keys(), 0..) |step_index, i| { print_node.last = i + 1 == last_index; printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) { error.Canceled => |e| return e, @@ -2401,7 +2464,7 @@ fn makeStepNames( w.writeByte('\n') catch {}; } - if (maker.watch or maker.web_server != null) return; + if (maker.watch or maker.web_server != null or maker.protocol_server != null) return; const code: u8 = code: { if (failure_count == 0) break :code 0; // success diff --git a/lib/std/zig/Client.zig b/lib/std/zig/Client.zig index df4eb067bd7867ab5898cf1d27717b9bffd0a0ed..cedda191b99042affaba76eec838fd9f332abdbb 100644 --- a/lib/std/zig/Client.zig +++ b/lib/std/zig/Client.zig @@ -4,6 +4,7 @@ const std = @import("std"); const Io = std.Io; const Allocator = std.mem.Allocator; const assert = std.debug.assert; +const Configuration = std.Build.Configuration; const OutMessage = std.zig.Client.Message; const InMessage = std.zig.Server.Message; const Reader = Io.Reader; @@ -60,9 +61,28 @@ pub const Message = struct { /// The message body has the same format as in Server. new_fuzz_input, + /// Asks the server to run a list of steps. + /// Body is a `BuildSteps`. + /// This message only applies to the build system protocol. + bsp_build_steps = 0x80000000, + _, }; + /// Trailing: + /// * step_indices: [step_count]std.Build.Configuration.Step.Index, + pub const BuildSteps = extern struct { + step_count: u32, + flags: Flags, + + pub const Flags = packed struct(u32) { + /// Can only be enabled when the server declared support for file + /// watching. + watch: bool, + reserved: u31 = 0, + }; + }; + comptime { assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1); } @@ -140,3 +160,21 @@ pub fn serveRunFuzzTestMessage( } try c.out.flush(); } + +pub fn serveBuildSteps( + c: *const Client, + steps: []const Configuration.Step.Index, + flags: OutMessage.BuildSteps.Flags, +) !void { + try c.serveMessageHeader(.{ + .tag = .bsp_build_steps, + .bytes_len = @intCast(@sizeOf(OutMessage.BuildSteps) + steps.len * @sizeOf(Configuration.Step.Index)), + }); + const body: OutMessage.BuildSteps = .{ + .step_count = @intCast(steps.len), + .flags = flags, + }; + try c.out.writeStruct(body, .little); + try c.out.writeSliceEndian(Configuration.Step.Index, steps, .little); + try c.out.flush(); +} diff --git a/tools/bsp.zig b/tools/bsp.zig index 875fda3e772739f6c337355027c84784e8e9a2d3..afa16d58d0fd23f3eeefe3c6ddaf12849b1e1746 100644 --- a/tools/bsp.zig +++ b/tools/bsp.zig @@ -143,7 +143,32 @@ pub fn main(init: std.process.Init) !void { if (std.mem.startsWith(u8, command, "build") or std.mem.startsWith(u8, command, "watch")) { - @panic("TODO"); + var steps: std.ArrayList(Configuration.Step.Index) = .empty; + defer steps.deinit(gpa); + + const watch = std.mem.startsWith(u8, command, "watch"); + + if (std.mem.cutPrefix(u8, command, "build ") orelse + std.mem.cutPrefix(u8, command, "watch ")) |command_args| + { + var it = std.mem.tokenizeScalar(u8, command_args, ' '); + while (it.next()) |arg| { + const step: Configuration.Step.Index = + if (std.fmt.parseInt(u32, arg, 10)) |i| + @fromBackingInt(i) + else |_| + top_level_steps.get(arg) orelse std.debug.panic("unexpected step name or index", .{}); + try steps.append(gpa, step); + } + } + + if (steps.items.len < 1) { + try steps.append(gpa, c.default_step); + } + + try client.serveBuildSteps(steps.items, .{ .watch = watch }); + + continue; } else if (std.mem.eql(u8, command, "exit")) { try client.serveBodylessMessage(.exit); break; -- 2.54.0 From 38efc69dc98f8548d473eeee24ea0717d07af11e Mon Sep 17 00:00:00 2001 From: Techatrix Date: Tue, 21 Jul 2026 16:29:09 +0200 Subject: [PATCH 018/215] Maker: serve build status over protocol --- lib/compiler/Maker.zig | 104 +++++++++++++++++++++++++++++++++-------- lib/std/zig/Server.zig | 36 ++++++++++++++ tools/bsp.zig | 21 +++++++++ 3 files changed, 142 insertions(+), 19 deletions(-) diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 61e815370fd9952163dfd9f2f0f29afb3380791d..12cf637975aa43832d01c3e84486f157606d43b4 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -897,19 +897,8 @@ pub fn main(init: process.Init.Minimal) !void { error.WriteFailed => return stderr.file_writer.err.?, }; }) { - if (web_server) |ws| ws.startBuild(); - try maker.makeSteps(main_progress_node, fuzz); - if (web_server) |ws| { - if (fuzz) |mode| if (mode != .forever) fatal( - "error: limited fuzzing is not implemented yet for --webui", - .{}, - ); - - ws.finishBuild(.{ .fuzz = fuzz != null }); - } - if (web_server) |ws| { const c = &scanned_config.configuration; assert(!watch); // fatal error after CLI parsing @@ -2254,6 +2243,12 @@ fn makeSteps( const top_level_steps = &maker.scanned_config.top_level_steps; const c = &maker.scanned_config.configuration; + if (maker.web_server) |ws| ws.startBuild(); + + if (maker.protocol_server) |s| { + try s.serveBodylessMessage(.bsp_build_started); + } + { // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer, // then spawn them. The buffer is so that we don't race with `makeStep` and end up thinking @@ -2279,6 +2274,19 @@ fn makeSteps( try group.await(io); } + if (maker.web_server) |ws| { + if (fuzz) |mode| if (mode != .forever) fatal( + "error: limited fuzzing is not implemented yet for --webui", + .{}, + ); + + ws.finishBuild(.{ .fuzz = fuzz != null }); + } + + if (maker.protocol_server) |s| { + try s.serveBodylessMessage(.bsp_build_completed); + } + assert(maker.memory_blocked_steps.items.len == 0); var test_pass_count: usize = 0; @@ -2539,6 +2547,15 @@ fn makeStep( defer step_prog_node.end(); if (maker.web_server) |ws| ws.updateStepStatus(step_index, .wip); + if (maker.protocol_server) |s| { + maker.protocol_server_mutex.lockUncancelable(io); + defer maker.protocol_server_mutex.unlock(io); + + s.serveU32Message( + .bsp_step_started, + @backingInt(step_index), + ) catch @panic("TODO propagate error when failing to send protocol message"); + } const new_state: Step.State = for (deps) |dep_index| { const dep_make_step = maker.stepByIndex(dep_index); @@ -2564,7 +2581,7 @@ fn makeStep( @atomicStore(Step.State, &make_step.state, new_state, .monotonic); - switch (new_state) { + const success = switch (new_state) { .precheck_unstarted => unreachable, .precheck_started => unreachable, .precheck_done => unreachable, @@ -2572,17 +2589,37 @@ fn makeStep( .failure, .dependency_failure, .skipped_oom, - => { - if (maker.web_server) |ws| ws.updateStepStatus(step_index, .failure); - std.Progress.setStatus(.failure_working); - }, + => false, .success, .skipped, - => { - if (maker.web_server) |ws| ws.updateStepStatus(step_index, .success); - }, + => true, + }; + + if (maker.web_server) |ws| { + ws.updateStepStatus(step_index, if (success) .success else .failure); } + if (maker.protocol_server != null) { + maker.protocol_server_mutex.lockUncancelable(io); + defer maker.protocol_server_mutex.unlock(io); + + const status: Server.Message.BuildStepCompleted.Status = switch (new_state) { + .precheck_unstarted => unreachable, + .precheck_started => unreachable, + .precheck_done => unreachable, + .success => .success, + .failure, .dependency_failure => .failure, + .skipped => .skipped, + .skipped_oom => .skipped_oom, + }; + serveBuildStepCompleted( + maker, + step_index, + status, + ) catch |err| std.debug.panic("TODO propagate error when failing to send protocol message: {t}", .{err}); + } + + if (!success) std.Progress.setStatus(.failure_working); } // No matter the result, we want to display error/warning messages. @@ -3152,6 +3189,35 @@ fn serveBSPHandshake(s: *const std.zig.Server) !void { try s.out.flush(); } +fn serveBuildStepCompleted( + maker: *Maker, + step_index: Configuration.Step.Index, + status: Server.Message.BuildStepCompleted.Status, +) !void { + const s: *Server = maker.protocol_server.?; + const step = maker.stepByIndex(step_index); + const error_bundle = step.result_error_bundle; + + const body: Server.Message.BuildStepCompleted = .{ + .step_index = step_index, + .status = status, + .error_bundle = .{ + .extra_len = @intCast(error_bundle.extra.len), + .string_bytes_len = @intCast(error_bundle.string_bytes.len), + }, + }; + const eb_bytes_len = @sizeOf(u32) * error_bundle.extra.len + error_bundle.string_bytes.len; + const bytes_len = @sizeOf(Server.Message.BuildStepCompleted) + eb_bytes_len; + try s.serveMessageHeader(.{ + .tag = .bsp_step_completed, + .bytes_len = @intCast(bytes_len), + }); + try s.out.writeStruct(body, .little); + try s.out.writeSliceEndian(u32, error_bundle.extra, .little); + try s.out.writeAll(error_bundle.string_bytes); + try s.out.flush(); +} + fn initStdoutWriter(io: Io) *Writer { stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); return &stdout_writer_allocation.interface; diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index 1da63f95310b561f4264771a271fe70346c82fe7..1f6d208084abdcc9d93ef33929e36aa0239549af 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -82,6 +82,18 @@ pub const Message = struct { /// Body is a cwd relative path to the configuration file. /// This message only applies to the build system protocol. bsp_configuration, + /// Does not have a body. + /// This message only applies to the build system protocol. + bsp_build_started, + /// Does not have a body. + /// This message only applies to the build system protocol. + bsp_build_completed, + /// Body is a `Configuration.Step.Index`. + /// This message only applies to the build system protocol. + bsp_step_started, + /// Body is a `BuildStepCompleted`. + /// This message only applies to the build system protocol. + bsp_step_completed, _, }; @@ -99,6 +111,25 @@ pub const Message = struct { }; }; + /// Trailing: + /// * error_bundle: ErrorBundle, + pub const BuildStepCompleted = extern struct { + step_index: std.Build.Configuration.Step.Index, + status: Status, + error_bundle: ErrorBundle, + // TODO result_error_msgs + // TODO result_stderr + // TODO result_peak_rss + // TODO result_duration_ns + + pub const Status = enum(u32) { + success, + failure, + skipped, + skipped_oom, + }; + }; + pub const PathPrefix = enum(u8) { cwd, zig_lib, @@ -194,6 +225,11 @@ pub fn serveMessageHeader(s: *const Server, header: OutMessage.Header) !void { try s.out.writeStruct(header, .little); } +pub fn serveBodylessMessage(s: *const Server, tag: OutMessage.Tag) Writer.Error!void { + try s.serveMessageHeader(.{ .tag = tag, .bytes_len = 0 }); + try s.out.flush(); +} + pub fn serveU32Message(s: *const Server, tag: OutMessage.Tag, int: u32) !void { try serveMessageHeader(s, .{ .tag = tag, diff --git a/tools/bsp.zig b/tools/bsp.zig index afa16d58d0fd23f3eeefe3c6ddaf12849b1e1746..bab0bc2c70afb95e99eb51ccf29be357ce4a678f 100644 --- a/tools/bsp.zig +++ b/tools/bsp.zig @@ -168,6 +168,27 @@ pub fn main(init: std.process.Init) !void { try client.serveBuildSteps(steps.items, .{ .watch = watch }); + while (true) { + const header: Server.Message.Header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { + error.Canceled, error.ConcurrencyUnavailable => |e| return e, + error.Timeout => unreachable, + else => |e| { + log.err("failed to receive message: {t}", .{err}); + break :blk e; + }, + }; + const body = client_stdout.take(header.bytes_len) catch unreachable; + log.debug("received {f} ({d} bytes)", .{ fmtEnum(header.tag), body.len }); + + switch (header.tag) { + .bsp_build_started => {}, + .bsp_build_completed => if (!watch) break, + .bsp_step_started => {}, + .bsp_step_completed => {}, + .bsp_configuration => @panic("TODO"), + else => std.debug.panic("received unexpected message: {f}", .{fmtEnum(header.tag)}), + } + } continue; } else if (std.mem.eql(u8, command, "exit")) { try client.serveBodylessMessage(.exit); -- 2.54.0 From f0b768988d2c28f854195212d98b4fd3a7f654da Mon Sep 17 00:00:00 2001 From: Techatrix Date: Mon, 13 Jul 2026 00:06:57 +0200 Subject: [PATCH 019/215] do not inherit stdio of run step when running the build system protocol --- lib/compiler/Maker/Step/Run.zig | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index 488225aadca8deb146e8fc1a2fd4c196c3811b2f..9da088639e68ef12d2b1ce65928ac0f86006ad06 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -2201,25 +2201,35 @@ fn spawnChildAndCollect( assert(conf_run.flags.stdio != .inherit); break :s .pipe; } else switch (conf_run.flags.stdio) { - .infer_from_args => if (has_side_effects) .inherit else .ignore, + .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .ignore, .inherit => .inherit, .check => .ignore, .zig_test => .pipe, }, .stdout = if (conf_run.captured_stdout.value != null) .pipe else switch (conf_run.flags.stdio) { - .infer_from_args => if (has_side_effects) .inherit else .ignore, + .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .ignore, .inherit => .inherit, .check => if (checksContainStdout(&conf_run)) .pipe else .ignore, .zig_test => .pipe, }, .stderr = if (conf_run.captured_stderr.value != null) .pipe else switch (conf_run.flags.stdio) { - .infer_from_args => if (has_side_effects) .inherit else .pipe, - .inherit => .inherit, + .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .pipe, + .inherit => if (maker.protocol_server == null) .inherit else .pipe, .check => .pipe, .zig_test => .pipe, }, }; + if (maker.protocol_server != null) { + if (spawn_options.stdin == .inherit) { + return step.fail(maker, "Cannot inherit stdin when running through over the build system protocol", .{}); + } + if (spawn_options.stdout == .inherit) { + return step.fail(maker, "Cannot inherit stdout when running through over the build system protocol", .{}); + } + assert(spawn_options.stderr != .inherit); + } + if (conf_run.flags.stdio == .zig_test) { try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?); const started: Io.Clock.Timestamp = .now(io, .awake); -- 2.54.0 From d697d97a95688e873d2677367e94010cdaa3ac73 Mon Sep 17 00:00:00 2001 From: Techatrix Date: Sun, 19 Jul 2026 01:10:14 +0200 Subject: [PATCH 020/215] std.mem: replace `byteSwapAllFields` with `byteSwap` The attached doc comment claims to only support structs even though the implementation also supports unions, arrays and integers. And unlike `byteSwapAllElements` it doesn't support enums and floats. booleans were only supported when they we're nested in a struct. A check to reject auto layout structs was missing as well. This function is used by the endianness aware functions in Reader and Writer which prevented some arbitrary types from being supported. --- lib/std/Io/Reader.zig | 8 ++-- lib/std/mem.zig | 109 +++++++++++++++++++++++++----------------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index 68cae96c836d7cab147c327afd06588c118d784c..966af7879c2488a2b8447f6398aa036a79aba263 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -718,7 +718,7 @@ pub inline fn readSliceEndian( endian: std.builtin.Endian, ) Error!void { try readSliceAll(r, @ptrCast(buffer)); - if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem); + if (native_endian != endian) std.mem.byteSwapAllElements(Elem, buffer); } pub const ReadAllocError = Error || Allocator.Error; @@ -734,8 +734,7 @@ pub inline fn readSliceEndianAlloc( ) ReadAllocError![]Elem { const dest = try allocator.alloc(Elem, len); errdefer allocator.free(dest); - try readSliceAll(r, @ptrCast(dest)); - if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem); + try r.readSliceEndian(Elem, dest, endian); return dest; } @@ -1227,8 +1226,7 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia .auto => @compileError("ill-defined memory layout"), .@"extern" => { var res: T = undefined; - try r.readSliceAll(std.mem.asBytes(&res)); - if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); + try r.readSliceEndian(T, (&res)[0..1], endian); return res; }, .@"packed" => { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8353c0ca8e209dd1516371926e0fbfd00f874ded..e35e92471f629a738bddf9a590ccaf937166f14d 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2215,33 +2215,54 @@ test writeVarPackedInt { try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st); } -/// Swap the byte order of all the members of the fields of a struct -/// (Changing their endianness) -pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { - byteSwapAllFieldsAligned(S, .of(S), ptr); +/// Deprecated: use `byteSwap` instead. +pub const byteSwapAllFields = byteSwap; + +/// Deprecated: use `byteSwapAligned` instead. +pub const byteSwapAllFieldsAligned = byteSwapAligned; + +/// Reverses the byte order. +/// Handles structs, unions, arrays, enums, floats, and integers recursively. +/// The order of extern struct fields and array elements remains unchanged and +/// will be byte swapped recursively. +/// Useful for converting between little-endian and big-endian representations. +pub fn byteSwap(comptime S: type, ptr: *S) void { + byteSwapAligned(S, .of(S), ptr); } -/// Swap the byte order of all the members of the fields of a struct -/// (Changing their endianness) -pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void { +/// Reverses the byte order. +/// Handles structs, unions, arrays, enums, floats, and integers recursively. +/// The order of extern struct fields and array elements remains unchanged and +/// will be byte swapped recursively. +/// Useful for converting between little-endian and big-endian representations. +pub fn byteSwapAligned( + comptime S: type, + comptime a: Alignment, + ptr: *align(a.toByteUnits()) S, +) void { switch (@typeInfo(S)) { .@"struct" => |@"struct"| { if (@"struct".backing_integer) |Int| { ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); - } else inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| { - switch (@typeInfo(f_type)) { - .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), - .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), - .@"enum" => { - @field(ptr, f_name) = @fromBackingInt(@intCast(@byteSwap(@backingInt(@field(ptr, f_name))))); - }, - .bool => {}, - .float => |float| { - @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); - }, - else => { - @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); - }, + } else { + if (@"struct".layout != .@"extern") { + @compileError("byteSwapAligned expects a packed or extern struct"); + } + inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| { + switch (@typeInfo(f_type)) { + .@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), + .@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), + .@"enum" => { + @field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name)))); + }, + .bool => {}, + .float => |float| { + @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); + }, + else => { + @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); + }, + } } } }, @@ -2249,7 +2270,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); } else { if (@"union".layout != .@"extern") { - @compileError("byteSwapAllFields expects a packed or extern union"); + @compileError("byteSwapAligned expects a packed or extern union"); } const first_size = @bitSizeOf(@"union".field_types[0]); @@ -2266,13 +2287,21 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a .array => |array| { byteSwapAllElements(array.child, ptr); }, + .@"enum" => { + ptr.* = @fromBackingInt(@byteSwap(@backingInt(ptr.*))); + }, + .bool => {}, + .float => |float| { + const int_repr: @Int(.unsigned, float.bits) = @bitCast(ptr.*); + ptr.* = @bitCast(@byteSwap(int_repr)); + }, else => { ptr.* = @byteSwap(ptr.*); }, } } -test byteSwapAllFields { +test byteSwap { const T = extern struct { f0: u8, f1: u16, @@ -2304,6 +2333,9 @@ test byteSwapAllFields { } align(4), f2: u32, }; + const E = enum(u32) { + _, + }; var s = T{ .f0 = 0x12, .f1 = 0x1234, @@ -2327,10 +2359,14 @@ test byteSwapAllFields { .f1 = .{ .f0 = 0x123456789ABCDEF0 }, .f2 = 0x87654321, }; - byteSwapAllFields(T, &s); - byteSwapAllFields(K, &k); - byteSwapAllFields(P, &p); - byteSwapAllFields(A, &a); + var e: E = @fromBackingInt(0x12345678); + var f: f32 = @bitCast(@as(u32, 0x4640e400)); + byteSwap(T, &s); + byteSwap(K, &k); + byteSwap(P, &p); + byteSwap(A, &a); + byteSwap(E, &e); + byteSwap(f32, &f); try std.testing.expectEqual(T{ .f0 = 0x12, .f1 = 0x3412, @@ -2354,28 +2390,15 @@ test byteSwapAllFields { .f1 = .{ .f0 = 0xF0DEBC9A78563412 }, .f2 = 0x21436587, }, a); + try std.testing.expectEqual(@as(E, @fromBackingInt(0x78563412)), e); + try std.testing.expectEqual(@as(f32, @bitCast(@as(u32, 0x00e44046))), f); } /// Reverses the byte order of all elements in a slice. /// Handles structs, unions, arrays, enums, floats, and integers recursively. /// Useful for converting between little-endian and big-endian representations. pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void { - for (slice) |*elem| { - switch (@typeInfo(@TypeOf(elem.*))) { - .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem), - .@"enum" => { - elem.* = @fromBackingInt(@intCast(@byteSwap(@backingInt(elem.*)))); - }, - .bool => {}, - .float => |float| { - const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*); - elem.* = @bitCast(@byteSwap(int_repr)); - }, - else => { - elem.* = @byteSwap(elem.*); - }, - } - } + for (slice) |*elem| byteSwap(Elem, elem); } /// Returns an iterator that iterates over the slices of `buffer` that are not -- 2.54.0 From 5fe9620b779d27fad84c3f3c11d038aa68faba2c Mon Sep 17 00:00:00 2001 From: avalyn0x45 Date: Tue, 21 Jul 2026 19:54:03 +0200 Subject: [PATCH 021/215] Remove erroneous quote in std.spirv.specConst inline asm (#36230) This seems to be an accidental inclusion from a copy+paste and stops function from being used with ints. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36230 Reviewed-by: Ali Cheraghi --- lib/std/spirv.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/spirv.zig b/lib/std/spirv.zig index 72ca757610e55922d552ccd8fb812b349d3f5c5f..f0b768ed1a1aeafb81a630257daab8290e772dde 100644 --- a/lib/std/spirv.zig +++ b/lib/std/spirv.zig @@ -97,7 +97,7 @@ pub fn specConst(T: type, comptime default_value: T, comptime spec_id: u32) T { }, .int, .float => return asm ( \\%ret = OpSpecConstant %ty $default_value - \\ OpDecorate %ret SpecId $spec_id" + \\ OpDecorate %ret SpecId $spec_id : [ret] "" (-> T), : [ty] "t" (T), [default_value] "c" (default_value), -- 2.54.0 From f22d73386441714d59ea080f165979e18204a09d Mon Sep 17 00:00:00 2001 From: Pavel Verigo Date: Thu, 16 Jul 2026 21:34:40 +0200 Subject: [PATCH 022/215] std: wasi dirDeleteFile check for directory for PERM/ACCES error --- lib/std/Io/Threaded.zig | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index d1ba12a8e29f0b9c38915cacbe04514303cc06dc..5b230064199c4d90df6c9e5ce7ecf155dcd46313 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -7119,9 +7119,10 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir. if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path); const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; + const wasi = std.os.wasi; const syscall: Syscall = try .start(); while (true) { - const res = std.os.wasi.path_unlink_file(dir.handle, sub_path.ptr, sub_path.len); + const res = wasi.path_unlink_file(dir.handle, sub_path.ptr, sub_path.len); switch (res) { .SUCCESS => { syscall.finish(); @@ -7131,11 +7132,35 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir. try syscall.checkCancel(); continue; }, + .ACCES, .PERM => |e| { + const original_error: Dir.DeleteFileError = switch (e) { + .ACCES => error.AccessDenied, + .PERM => error.PermissionDenied, + else => unreachable, + }; + var stat: wasi.filestat_t = undefined; + while (true) { + try syscall.checkCancel(); + switch (wasi.path_filestat_get(dir.handle, .{}, sub_path.ptr, sub_path.len, &stat)) { + .SUCCESS => { + syscall.finish(); + break; + }, + .INTR => continue, + else => { + syscall.finish(); + return original_error; + }, + } + } + if (stat.filetype == .DIRECTORY) + return error.IsDir + else + return original_error; + }, else => |e| { syscall.finish(); switch (e) { - .ACCES => return error.AccessDenied, - .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .FAULT => |err| return errnoBug(err), .IO => return error.FileSystem, -- 2.54.0 From 2b1c6633aaf1d59d4affd88e87a507a02836c478 Mon Sep 17 00:00:00 2001 From: Kleshzz Date: Wed, 22 Jul 2026 09:34:43 +0200 Subject: [PATCH 023/215] spirv: fix ICEs when indexing slices, emitting large instructions (#36253) Fixes #36229 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36253 Reviewed-by: Ali Cheraghi --- src/codegen/spirv/Section.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/codegen/spirv/Section.zig b/src/codegen/spirv/Section.zig index 6207cc787cd0c187c8199fc54efd7c9aaf451efc..fcd7739c1dd3a6916a258e79ce36dae6fec3ba2c 100644 --- a/src/codegen/spirv/Section.zig +++ b/src/codegen/spirv/Section.zig @@ -49,8 +49,9 @@ pub fn emitRaw( operand_words: usize, ) !void { const word_count = 1 + operand_words; + if (word_count > std.math.maxInt(u16)) return error.OutOfMemory; try section.instructions.ensureUnusedCapacity(allocator, word_count); - section.writeWord((@as(Word, @intCast(word_count << 16))) | @backingInt(opcode)); + section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode)); } /// Write an entire instruction, including all operands @@ -70,7 +71,8 @@ pub fn emitAssumeCapacity( operands: opcode.Operands(), ) !void { const word_count = instructionSize(opcode, operands); - section.writeWord(@as(Word, @intCast(word_count << 16)) | @backingInt(opcode)); + if (word_count > std.math.maxInt(u16)) return error.OutOfMemory; + section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode)); section.writeOperands(opcode.Operands(), operands); } @@ -81,8 +83,9 @@ pub fn emit( operands: opcode.Operands(), ) !void { const word_count = instructionSize(opcode, operands); + if (word_count > std.math.maxInt(u16)) return error.OutOfMemory; try section.instructions.ensureUnusedCapacity(allocator, word_count); - section.writeWord(@as(Word, @intCast(word_count << 16)) | @backingInt(opcode)); + section.writeWord((@as(Word, @intCast(word_count)) << 16) | @backingInt(opcode)); section.writeOperands(opcode.Operands(), operands); } -- 2.54.0 From aad9870a284410b9b7fa4d5c5d84f4a4d697c71b Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sun, 19 Jul 2026 14:26:35 -0700 Subject: [PATCH 024/215] Io.Threaded: Decouple follow_symlinks and asynchronous IO on Windows The logic around follow_symlinks and asynchronous IO was first introduced in 66bbe4ec4c11839217d6a9d65771d60d45cd6bc1, and then cemented in 390194431e7fa439d67686e5a0e9efceed2d898a with the added comment: > If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. As far as I can tell, this comment is erroneous. There is no documented incompatibility between OPEN_REPARSE_POINT and SYNCHRONOUS_IO_NONALERT, and empirically everything works fine when using SYNCHRONOUS_IO_NONALERT. In fact, in 68ed787751ed36af3db0c52031741a5c31413034 the ReadLink implementation (a main usage of OPEN_REPARSE_POINT) was specifically switched to *not* use asynchronous IO (although that was effectively reverted during the move to std.Io). This also fixes a bug with `.follow_symlinks = false` since, before this commit, the returned File would always have `.nonblocking = false` even though that was not correct when `.follow_symlinks` was false. --- lib/std/Io/Threaded.zig | 8 ++++---- lib/std/fs/test.zig | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 5b230064199c4d90df6c9e5ce7ecf155dcd46313..04384b3d68e4e8c26f610731479f4ec435c7cc44 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -5053,7 +5053,7 @@ pub fn dirOpenFileWtf16( .VALID_FLAGS, .OPEN, .{ - .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .NON_DIRECTORY_FILE = !allow_directory, .OPEN_REPARSE_POINT = !flags.follow_symlinks, }, @@ -8136,7 +8136,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink .{ .DIRECTORY_FILE = false, .NON_DIRECTORY_FILE = false, - .IO = .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .OPEN_REPARSE_POINT = true, }, null, @@ -8202,7 +8202,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined; switch ((try deviceIoControl(&.{ - .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } }, + .file = .{ .handle = result_handle, .flags = .{ .nonblocking = false } }, .code = .GET_REPARSE_POINT, .out = &reparse_buf, })).u.Status) { @@ -18995,7 +18995,7 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows .{ .DIRECTORY_FILE = options.filter == .dir_only, .NON_DIRECTORY_FILE = options.filter == .non_directory_only, - .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .OPEN_REPARSE_POINT = !options.follow_symlinks, }, null, diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index bf16a7c216b4f9087195c7a98160e6b765687960..fc613ccdaa313d46dab643f849149293f422a9a5 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -758,6 +758,43 @@ test "readFileAlloc" { ); } +test "file operations with follow_symlinks=false" { + const io = testing.io; + + var tmp_dir = tmpDir(.{}); + defer tmp_dir.cleanup(); + + const contents = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; + try tmp_dir.dir.writeFile(io, .{ + .sub_path = "test_file", + .data = contents, + }); + + // Without lock + { + var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false }); + defer file.close(io); + + var file_reader = file.reader(io, &.{}); + const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited); + defer testing.allocator.free(actual_contents); + + try std.testing.expectEqualSlices(u8, contents, actual_contents); + } + + // With lock + { + var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false, .lock = .exclusive }); + defer file.close(io); + + var file_reader = file.reader(io, &.{}); + const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited); + defer testing.allocator.free(actual_contents); + + try std.testing.expectEqualSlices(u8, contents, actual_contents); + } +} + test "Dir.statFile" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { -- 2.54.0 From cad234174ae7ae990ebc526b6fcd92d18516e3c1 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 22 Jul 2026 20:23:36 +0200 Subject: [PATCH 025/215] llvm: fix address space of global aliases #32108 contains my process for root causing this issue. In short, while the LLVM language does not associate aliases with address spaces, the address space does get serialized alongside the alias, and that value was hardcoded to `.default`, and the error observed was from a failed sanity check. I added an assertion on the serialization side and observed it get hit, showing the difference in address space. I followed that up with a patch to grab the address space from the aliasee instead of hardcoding it. The AVR repro now compiles: ```zig export fn anything() void {} ``` Fixes: https://codeberg.org/ziglang/zig/issues/32108 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36146 --- lib/std/zig/llvm/Builder.zig | 5 ++++- src/codegen/llvm.zig | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 38c6a53cdd13c50fe4e6a0a172649647a94bfb3b..d0e86c80ac3baa8c9504095b8200b546789a39b2 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -13955,8 +13955,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco } const strtab = alias.global.strtab(self); - const global = alias.global.ptrConst(self); + + // LLVM requires the types to match + assert(global.addr_space == alias.aliasee.typeOf(self).pointerAddrSpace(self)); + try module_block.writeAbbrev(ModuleBlock.Alias{ .strtab_offset = strtab.offset, .strtab_size = strtab.size, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2405f51b3e90f9dab947bcef12f778445f2a3f64..12422f9f6f8ba5609730e1f38e37960951409174 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1661,7 +1661,7 @@ pub const Object = struct { const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - .default, + global_index.ptrConst(&o.builder).addr_space, global_index.toConst(), ); break :global alias.ptrConst(&o.builder).global; @@ -1673,6 +1673,10 @@ pub const Object = struct { // We can just repurpose the existing alias. alias.setAliasee(global_index.toConst(), &o.builder); alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder); + // If the type the alias is pointing to can change, then + // it makes sense that we should update the address + // space too. + alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = global_index.ptrConst(&o.builder).addr_space; break :global existing_global; }, .variable, .function => { @@ -1687,7 +1691,7 @@ pub const Object = struct { const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - .default, + global_index.ptrConst(&o.builder).addr_space, global_index.toConst(), ); break :global alias.ptrConst(&o.builder).global; -- 2.54.0 From 5da11070e9851d15b7c6200006ae525a22ef8c18 Mon Sep 17 00:00:00 2001 From: EJ Date: Wed, 22 Jul 2026 20:31:11 +0200 Subject: [PATCH 026/215] Test that Allocator interface avoids IB for max size allocations (#35437) Closes [#6076](https://github.com/ziglang/zig/issues/6076) Tracking issue: #31661 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35437 --- lib/std/mem/Allocator.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig index 80341ecc2fa30523ef26bf7f1f68087fea18b925..486c69966e0e3d9bccf1b99e92d404cc36363283 100644 --- a/lib/std/mem/Allocator.zig +++ b/lib/std/mem/Allocator.zig @@ -587,4 +587,7 @@ fn unreachableFree( test failing { const f: Allocator = .failing; try std.testing.expectError(error.OutOfMemory, f.alloc(u8, 123)); + // Expect very large allocations to fail at the implementation level and not in the interface + try std.testing.expectError(error.OutOfMemory, f.alloc(u8, std.math.maxInt(usize))); + try std.testing.expectError(error.OutOfMemory, f.allocSentinel(u8, std.math.maxInt(usize) - 1, 0)); } -- 2.54.0 From 9a9d8adda017780956de9015db1858f48bc8f509 Mon Sep 17 00:00:00 2001 From: "Ashley (holtowd)" Date: Sat, 18 Jul 2026 21:32:58 +0300 Subject: [PATCH 027/215] Remove pub modifier from `const Self = @This()` expressions --- lib/std/meta/trailer_flags.zig | 2 +- lib/std/process/Args.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig index 3918f954143a73cc524c0aad7ac13835fb85fce3..acad4afabebd35ae58525f232906b793b04075d2 100644 --- a/lib/std/meta/trailer_flags.zig +++ b/lib/std/meta/trailer_flags.zig @@ -39,7 +39,7 @@ pub fn TrailerFlags(comptime Fields: type) type { break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs); }; - pub const Self = @This(); + const Self = @This(); pub fn has(self: Self, comptime field: FieldEnum) bool { const field_index = @backingInt(field); diff --git a/lib/std/process/Args.zig b/lib/std/process/Args.zig index 8e6caf2d651d407a2baaab7b276f0f187381f068..35e5b7cce411f9064a76dfe7f223d531f9f848c2 100644 --- a/lib/std/process/Args.zig +++ b/lib/std/process/Args.zig @@ -752,7 +752,7 @@ pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type { start: usize = 0, end: usize = 0, - pub const Self = @This(); + const Self = @This(); pub const InitError = error{OutOfMemory}; -- 2.54.0 From 97527a42c5a09564fa94d491a0c1d48c0fe66e28 Mon Sep 17 00:00:00 2001 From: Kleshzz Date: Wed, 22 Jul 2026 17:43:11 +0300 Subject: [PATCH 028/215] spirv: improve Assembler source locations, error formatting --- src/codegen/spirv/Assembler.zig | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index aa80b4257ecc0756a463b58a550155ba56f22d04..5da442650eb089ecb89e68e9f9ffc21551adcf21 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -24,6 +24,7 @@ inst: struct { opcode: Opcode = undefined, operands: std.ArrayList(Operand) = .empty, string_bytes: std.ArrayList(u8) = .empty, + inst_offset: u32 = 0, fn result(ass: @This()) ?AsmValue.Ref { for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| { @@ -35,7 +36,7 @@ inst: struct { return null; } } = .{}, -value_map: std.array_hash_map.String(AsmValue) = .{}, +value_map: std.array_hash_map.String(AsmValue) = .empty, inst_map: std.array_hash_map.String(void) = .empty, const Operand = union(enum) { @@ -82,7 +83,7 @@ pub fn assemble(ass: *Assembler, src: []const u8) Error!void { if (ass.inst_map.count() == 0) { const instructions = spec.InstructionSet.core.instructions(); try ass.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len)); - for (spec.InstructionSet.core.instructions(), 0..) |inst, i| { + for (instructions, 0..) |inst, i| { const entry = try ass.inst_map.getOrPut(gpa, inst.name); assert(entry.index == i); } @@ -114,12 +115,13 @@ fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytyp } fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error { + @branchHint(.cold); try ass.addError(offset, fmt, args); return error.AssembleFail; } fn todo(ass: *Assembler, comptime fmt: []const u8, args: anytype) Error { - return ass.fail(0, "todo: " ++ fmt, args); + return ass.fail(ass.inst.inst_offset, "todo: " ++ fmt, args); } const AsmValue = union(enum) { @@ -209,9 +211,8 @@ fn processInstruction(ass: *Assembler) !void { switch (ass.value_map.values()[result_ref]) { .just_declared => ass.value_map.values()[result_ref] = result, else => { - // TODO: Improve source location. const name = ass.value_map.keys()[result_ref]; - return ass.fail(0, "duplicate definition of %{s}", .{name}); + return ass.fail(ass.inst.inst_offset, "duplicate definition of %{s}", .{name}); }, } } @@ -229,12 +230,11 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue { 0 => .unsigned, 1 => .signed, else => { - // TODO: Improve source location. - return ass.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); + return ass.fail(ass.inst.inst_offset, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); }, }; const width = std.math.cast(u16, operands[1].literal32) orelse { - return ass.fail(0, "int type of {} bits is too large", .{operands[1].literal32}); + return ass.fail(ass.inst.inst_offset, "int type of {} bits is too large", .{operands[1].literal32}); }; break :blk try cg.intType(signedness, width); }, @@ -243,7 +243,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue { switch (bits) { 16, 32, 64 => {}, else => { - return ass.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits}); + return ass.fail(ass.inst.inst_offset, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits}); }, } break :blk try cg.floatType(@intCast(bits)); @@ -445,11 +445,11 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue { const gpa = cg.gpa; const ty_ref = switch (ass.inst.operands.items[0]) { .ref_id => |i| i, - else => return ass.fail(0, "missing result type", .{}), + else => return ass.fail(ass.inst.inst_offset, "missing result type", .{}), }; const composite_ty_id = switch (try ass.resolveRef(ty_ref)) { .ty => |id| id, - else => return ass.fail(0, "%ty must be a type", .{}), + else => return ass.fail(ass.inst.inst_offset, "%ty must be a type", .{}), }; const globals = &cg.sections.globals; @@ -483,7 +483,7 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue { } const spec_id_word = std.math.cast(u32, spec_id_base + i) orelse { - return ass.fail(0, "SpecId {} does not fit in 32 bits", .{spec_id_base + i}); + return ass.fail(ass.inst.inst_offset, "SpecId {} does not fit in 32 bits", .{spec_id_base + i}); }; try annotations.emitRaw(gpa, .OpDecorate, 3); annotations.writeOperand(Id, elem_id); @@ -505,8 +505,7 @@ fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { switch (value) { .just_declared => { const name = ass.value_map.keys()[ref]; - // TODO: Improve source location. - return ass.fail(0, "ass-referential parameter %{s}", .{name}); + return ass.fail(ass.inst.inst_offset, "self-referential parameter %{s}", .{name}); }, else => return value, } @@ -518,8 +517,7 @@ fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { .just_declared => unreachable, .unresolved_forward_reference => { const name = ass.value_map.keys()[ref]; - // TODO: Improve source location. - return ass.fail(0, "reference to undeclared result-id %{s}", .{name}); + return ass.fail(ass.inst.inst_offset, "reference to undeclared result-id %{s}", .{name}); }, else => return value, } @@ -536,6 +534,7 @@ fn parseInstruction(ass: *Assembler) !void { ass.inst.opcode = undefined; ass.inst.operands.clearRetainingCapacity(); ass.inst.string_bytes.clearRetainingCapacity(); + ass.inst.inst_offset = ass.currentToken().start; const lhs_result_tok = ass.currentToken(); const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: { @@ -589,8 +588,8 @@ fn parseInstruction(ass: *Assembler) !void { .required => if (ass.isAtInstructionBoundary()) { return ass.fail( ass.currentToken().start, - "missing required operand", // TODO: Operand name? - .{}, + "missing required operand '{s}'", + .{@tagName(operand.kind)}, ); } else { try ass.parseOperand(operand.kind); -- 2.54.0 From 8b2d0ce218db8d874cec1c11b3f186955af620c1 Mon Sep 17 00:00:00 2001 From: gDator Date: Thu, 23 Jul 2026 23:06:12 +0200 Subject: [PATCH 029/215] Io.Threaded: Implement fileLength without fileStat on Windows (#36293) Closes #36179 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36293 Reviewed-by: Ryan Liptak --- lib/std/Io/Threaded.zig | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 04384b3d68e4e8c26f610731479f4ec435c7cc44..457e4a255f857a80bd7f487b52c9db83027a4370 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -3858,7 +3858,26 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { } } } else if (is_windows) { - // TODO call NtQueryInformationFile and ask for only the size instead of "all" + var io_status_block: windows.IO_STATUS_BLOCK = undefined; + var info: windows.FILE.STANDARD_INFORMATION = undefined; + const syscall: Syscall = try .start(); + while (true) switch (windows.ntdll.NtQueryInformationFile( + file.handle, + &io_status_block, + &info, + @sizeOf(windows.FILE.STANDARD_INFORMATION), + .Standard, + )) { + .SUCCESS => break syscall.finish(), + .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), + .ACCESS_DENIED => return syscall.fail(error.AccessDenied), + .CANCELLED => { + try syscall.checkCancel(); + continue; + }, + else => |s| return syscall.unexpectedNtstatus(s), + }; + return @as(u64, @bitCast(info.EndOfFile)); } const stat = try fileStat(t, file); -- 2.54.0 From 619e54c81382d849f0bfcbe7e5c38f9b34390639 Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Fri, 22 May 2026 17:33:25 +0200 Subject: [PATCH 030/215] AstGen: add missing `pointer modifier invalid on discard` failure for switch This: ``` fn foo() void { if ({}) |*_| {} else |err| switch (err) {} } ``` now correctly produces the same compile error in `switchExpr` as this: ``` fn foo() void { if ({}) |*_| {} else |err| (switch (err) {}) } ``` does in `ifExpr`. --- lib/std/zig/AstGen.zig | 1 + test/cases/compile_errors/capture_by_ref_discard.zig | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index c865bd92fe1d3d69cf188cf295ba637ef70a0b9f..1408f3c6f037e6e802ce1944764722955faa1fd8 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -7453,6 +7453,7 @@ fn switchExpr( const ident_name = try astgen.identAsString(ident_token); const ident_name_str = tree.tokenSlice(ident_token); if (mem.eql(u8, "_", ident_name_str)) { + if (non_err_is_ref != .no) return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{}); break :scope &scratch_scope.base; } non_err_capture = if (non_err_is_ref != .no) .by_ref else .by_val; diff --git a/test/cases/compile_errors/capture_by_ref_discard.zig b/test/cases/compile_errors/capture_by_ref_discard.zig index 1779936d34fc04ef7f29a275886b1e8e47635d10..c407ede6c9dc4ba9a1db6aea344e5b34d06d5871 100644 --- a/test/cases/compile_errors/capture_by_ref_discard.zig +++ b/test/cases/compile_errors/capture_by_ref_discard.zig @@ -16,9 +16,14 @@ export fn d() void { while (null) |*_| {} } +export fn e() void { + if (0) |*_| {} else |err| switch (err) {} +} + // error // // :2:16: error: pointer modifier invalid on discard // :7:18: error: pointer modifier invalid on discard // :12:16: error: pointer modifier invalid on discard // :16:19: error: pointer modifier invalid on discard +// :20:13: error: pointer modifier invalid on discard -- 2.54.0 From d3056114f6f17bb4723cccfa4dd578ddafb909a9 Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Fri, 24 Jul 2026 16:50:07 +0200 Subject: [PATCH 031/215] Sema: disallow unreachable `else` prong for tagged unions with nonexhaustive tag types --- src/Sema.zig | 2 +- ...n_with_nonexhaustive_tag_is_exhaustive.zig | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig diff --git a/src/Sema.zig b/src/Sema.zig index 6dafdeb0ee6c53fb6f116272e28c641239573cff..a52b11b506a71f7d4c4c734dbded00d5f5996a40 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11375,7 +11375,7 @@ fn validateSwitchBlock( if (has_else) { if (all_tags_handled) { - if (item_ty.isNonexhaustiveEnum(zcu)) { + if (operand_ty.isNonexhaustiveEnum(zcu)) { if (has_under) return sema.fail( block, else_prong_src, diff --git a/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig b/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig new file mode 100644 index 0000000000000000000000000000000000000000..fc289fb55fb2c7fb0db1dd990fea16f431509595 --- /dev/null +++ b/test/cases/compile_errors/switch_on_union_with_nonexhaustive_tag_is_exhaustive.zig @@ -0,0 +1,56 @@ +const E = enum(u8) { + a, + b, + _, +}; +const U = union(E) { + a, + b, +}; +fn foo() U { + return undefined; +} + +export fn entry1() void { + const u = foo(); + switch (u) { + .a => {}, + } +} +export fn entry2() void { + const u = foo(); + switch (u) { + .a => {}, + .b => {}, + else => {}, + } +} +export fn entry3() void { + const u = foo(); + switch (u) { + .a => {}, + .b => {}, + _ => {}, + } +} +export fn entry4() void { + const u = foo(); + switch (u) { + .a => {}, + else => {}, + _ => {}, + } +} + +// error +// +// :16:5: error: switch must handle all possibilities +// :3:5: note: unhandled enumeration value: 'b' +// :1:11: note: enum 'tmp.E' declared here +// :25:14: error: unreachable else prong; all cases already handled +// :30:5: error: '_' prong only allowed when switching on non-exhaustive enums +// :33:9: note: '_' prong here +// :30:5: note: consider using 'else' +// :38:5: error: '_' prong only allowed when switching on non-exhaustive enums +// :41:9: note: '_' prong here +// :38:5: note: consider using 'else' -- 2.54.0 From e48779fe1f6127d50008277fb8662566769975da Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Fri, 22 May 2026 17:32:38 +0200 Subject: [PATCH 032/215] Sema: improve invalid switch type compile errors Makes them more similar to other existing compile errors. --- src/Sema.zig | 58 ++++++---- .../compile_errors/switch_on_invalid_type.zig | 103 ++++++++++++++++++ .../switch_on_non_packed_struct.zig | 25 ----- 3 files changed, 139 insertions(+), 47 deletions(-) create mode 100644 test/cases/compile_errors/switch_on_invalid_type.zig delete mode 100644 test/cases/compile_errors/switch_on_non_packed_struct.zig diff --git a/src/Sema.zig b/src/Sema.zig index a52b11b506a71f7d4c4c734dbded00d5f5996a40..e1035ea5d58e77d94e08725975cda95982c10ab0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11186,14 +11186,8 @@ fn validateSwitchBlock( operand_ty.assertHasLayout(zcu); const union_obj = ip.loadUnionType(operand_ty.toIntern()); switch (union_obj.tag_usage) { - .tagged => { - break :item_ty .fromInterned(union_obj.enum_tag_type); - }, - .none => { - if (union_obj.layout == .@"packed") { - break :item_ty operand_ty; - } - }, + .tagged => break :item_ty .fromInterned(union_obj.enum_tag_type), + .none => if (union_obj.layout == .@"packed") break :item_ty operand_ty, .safety => {}, } return sema.failWithOwnedErrorMsg(block, msg: { @@ -11208,27 +11202,47 @@ fn validateSwitchBlock( .@"struct" => { operand_ty.assertHasLayout(zcu); - const layout = operand_ty.containerLayout(zcu); - if (layout == .@"packed") { - break :item_ty operand_ty; - } + if (operand_ty.containerLayout(zcu) == .@"packed") break :item_ty operand_ty; return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(operand_src, "switch on struct with {t} layout", .{layout}); + const msg = try sema.errMsg(operand_src, "switch on non-packed struct", .{}); errdefer msg.destroy(sema.gpa); - if (operand_ty.srcLocOrNull(zcu)) |struct_src| { - try sema.errNote(struct_src, msg, "consider 'packed struct' here", .{}); - } + try sema.addDeclaredHereNote(msg, operand_ty); break :msg msg; }); }, - .pointer => { - if (!operand_ty.isSlice(zcu)) { - break :item_ty operand_ty; - } - }, + .pointer => if (!operand_ty.isSlice(zcu)) break :item_ty operand_ty, - else => {}, + .optional => return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(operand_src, "switch on optional type '{f}'", .{ + operand_ty.fmt(pt), + }); + errdefer msg.destroy(gpa); + try sema.errNote(operand_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); + break :msg msg; + }), + + .error_union => return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(operand_src, "switch on error union type '{f}'", .{ + operand_ty.fmt(pt), + }); + errdefer msg.destroy(gpa); + try sema.errNote(operand_src, msg, "consider using 'try', 'catch', or 'if'", .{}); + break :msg msg; + }), + + .noreturn, + .float, + .comptime_float, + .array, + .vector, + .undefined, + .null, + .@"opaque", + .frame, + .@"anyframe", + .spirv, + => {}, } return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); }; diff --git a/test/cases/compile_errors/switch_on_invalid_type.zig b/test/cases/compile_errors/switch_on_invalid_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..8d10d75a66c4b4f082bc83628cbc741090ff8428 --- /dev/null +++ b/test/cases/compile_errors/switch_on_invalid_type.zig @@ -0,0 +1,103 @@ +const AutoUnion = union { a: u8 }; +export fn entry1() void { + switch (@as(AutoUnion, .{ .a = 123 })) { + else => {}, + } +} + +const ExternUnion = union { a: u8 }; +export fn entry2() void { + switch (@as(ExternUnion, .{ .a = 123 })) { + else => {}, + } +} + +const AutoStruct = struct { a: u8 }; +export fn entry3() void { + switch (@as(AutoStruct, .{ .a = 123 })) { + else => {}, + } +} + +const ExternStruct = extern struct { a: u8 }; +export fn entry4() void { + switch (@as(ExternStruct, .{ .a = 123 })) { + else => {}, + } +} + +export fn entry5() void { + switch (@as([]const u16, &.{ 1, 2, 3 })) { + else => {}, + } +} + +export fn entry6() void { + switch (@as([3]u16, .{ 1, 2, 3 })) { + else => {}, + } +} + +export fn entry7() void { + switch (@as(@Vector(3, u16), .{ 1, 2, 3 })) { + else => {}, + } +} + +export fn entry8() void { + switch (@as(?u16, 123)) { + else => {}, + } +} + +export fn entry9() void { + switch (@as(anyerror!u16, 123)) { + else => {}, + } +} + +export fn entry10() void { + switch (@as(f32, 123)) { + else => {}, + } +} + +export fn entry11() void { + switch (@as(comptime_float, 123)) { + else => {}, + } +} + +export fn entry12() void { + switch (undefined) { + else => {}, + } +} + +export fn entry13() void { + switch (null) { + else => {}, + } +} + +// error +// +// :3:13: error: switch on union with no attached enum +// :1:19: note: consider 'union(enum)' here +// :10:13: error: switch on union with no attached enum +// :8:21: note: consider 'union(enum)' here +// :17:13: error: switch on non-packed struct +// :15:20: note: struct declared here +// :24:13: error: switch on non-packed struct +// :22:29: note: struct declared here +// :30:13: error: switch on type '[]const u16' +// :36:13: error: switch on type '[3]u16' +// :42:13: error: switch on type '@Vector(3, u16)' +// :48:13: error: switch on optional type '?u16' +// :48:13: note: consider using '.?', 'orelse', or 'if' +// :54:13: error: switch on error union type 'anyerror!u16' +// :54:13: note: consider using 'try', 'catch', or 'if' +// :60:13: error: switch on type 'f32' +// :66:13: error: switch on type 'comptime_float' +// :72:13: error: switch on type '@TypeOf(undefined)' +// :78:13: error: switch on type '@TypeOf(null)' diff --git a/test/cases/compile_errors/switch_on_non_packed_struct.zig b/test/cases/compile_errors/switch_on_non_packed_struct.zig deleted file mode 100644 index ef17bb3ca533361c38f1cb9caae5b391c1f4ab54..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/switch_on_non_packed_struct.zig +++ /dev/null @@ -1,25 +0,0 @@ -const Auto = struct { - a: u8, -}; -export fn entry1(a: u8) void { - const s: Auto = .{ .a = a }; - switch (s) { - else => {}, - } -} - -const Extern = extern struct { - a: u8, -}; -export fn entry2(s: Extern) void { - switch (s) { - else => {}, - } -} - -// error -// -// :6:13: error: switch on struct with auto layout -// :1:14: note: consider 'packed struct' here -// :15:13: error: switch on struct with extern layout -// :11:23: note: consider 'packed struct' here -- 2.54.0 From c1682a01c1c3994b3a30173197954ba65992bee1 Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Fri, 24 Jul 2026 14:34:00 +0200 Subject: [PATCH 033/215] Sema: improve switch duplicate item/range errors Now reports which values are duplicated and the overlap of duplicate ranges. --- src/RangeSet.zig | 41 ++- src/Sema.zig | 243 ++++++++++-------- .../duplicate_boolean_switch_value.zig | 4 +- .../duplicate_error_in_switch.zig | 2 +- ...expression-duplicate_enumeration_prong.zig | 3 +- ...te_enumeration_prong_when_else_present.zig | 3 +- ...witch_expression-duplicate_error_prong.zig | 4 +- ...uplicate_error_prong_when_else_present.zig | 4 +- ...duplicate_or_overlapping_integer_value.zig | 16 -- .../switch_expression-duplicate_type.zig | 2 +- ...expression-duplicate_type_struct_alias.zig | 3 +- .../switch_with_overlapping_case_ranges.zig | 42 ++- 12 files changed, 200 insertions(+), 167 deletions(-) delete mode 100644 test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig diff --git a/src/RangeSet.zig b/src/RangeSet.zig index 3033e8510394cbef68b815601f4eea545fb4feae..291b8ee4e5f001ac715113d63ea30d3f6e0bb6d8 100644 --- a/src/RangeSet.zig +++ b/src/RangeSet.zig @@ -1,6 +1,6 @@ const RangeSet = @This(); -ranges: std.MultiArrayList(Range), +list: std.MultiArrayList(Range), pub const Range = struct { first: Value, @@ -8,41 +8,36 @@ pub const Range = struct { src: LazySrcLoc, }; -pub const empty: RangeSet = .{ .ranges = .empty }; +pub const empty: RangeSet = .{ .list = .empty }; pub fn deinit(self: *RangeSet, allocator: Allocator) void { - self.ranges.deinit(allocator); + self.list.deinit(allocator); self.* = undefined; } -pub fn ensureUnusedCapacity(self: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void { - return self.ranges.ensureUnusedCapacity(allocator, additional_count); +pub fn ensureUnusedCapacity(set: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void { + return set.list.ensureUnusedCapacity(allocator, additional_count); } -pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?LazySrcLoc { +pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?Range { assert(new.first.typeOf(zcu).eql(ty)); assert(new.last.typeOf(zcu).eql(ty)); assert(new.first.compareScalar(.lte, new.last, ty, zcu)); - const idx = std.sort.lowerBound(Value, set.ranges.items(.last), @as(SearchCtx, .{ + const idx = std.sort.lowerBound(Value, set.list.items(.last), @as(SearchCtx, .{ .val = new.first, .zcu = zcu, }), compare); - if (idx != set.ranges.len and // `new.first` is *not* greater than all `old.last` - new.last.compareScalar(.gte, set.ranges.items(.first)[idx], ty, zcu)) + if (idx != set.list.len and // `new.first` is *not* greater than all `old.last` + new.last.compareScalar(.gte, set.list.items(.first)[idx], ty, zcu)) { - return set.ranges.items(.src)[idx]; // `new` overlaps with existing range. + return set.list.get(idx); // `new` overlaps with existing range. } - set.ranges.insertAssumeCapacity(idx, new); + set.list.insertAssumeCapacity(idx, new); return null; } -pub fn add(set: *RangeSet, allocator: Allocator, new: Range, ty: Type, zcu: *Zcu) Allocator.Error!?LazySrcLoc { - try set.ensureUnusedCapacity(allocator, 1); - return set.addAssumeCapacity(new, ty, zcu); -} - pub fn spans( set: *RangeSet, allocator: Allocator, @@ -53,13 +48,13 @@ pub fn spans( ) Allocator.Error!bool { assert(first.typeOf(zcu).eql(ty)); assert(last.typeOf(zcu).eql(ty)); - if (set.ranges.len == 0) return false; + if (set.list.len == 0) return false; - assert(std.sort.isSorted(Value, set.ranges.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); - assert(std.sort.isSorted(Value, set.ranges.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); + assert(std.sort.isSorted(Value, set.list.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); + assert(std.sort.isSorted(Value, set.list.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); - if (!set.ranges.items(.first)[0].eql(first, ty, zcu) or - !set.ranges.items(.last)[set.ranges.len - 1].eql(last, ty, zcu)) + if (!set.list.items(.first)[0].eql(first, ty, zcu) or + !set.list.items(.last)[set.list.len - 1].eql(last, ty, zcu)) { return false; } @@ -75,8 +70,8 @@ pub fn spans( // look for gaps for ( - set.ranges.items(.first)[1..], - set.ranges.items(.last)[0 .. set.ranges.len - 1], + set.list.items(.first)[1..], + set.list.items(.last)[0 .. set.list.len - 1], ) |cur_first, prev_last| { // prev_last + 1 == cur_first counter.copy(prev_last.toBigInt(&space, zcu)); diff --git a/src/Sema.zig b/src/Sema.zig index e1035ea5d58e77d94e08725975cda95982c10ab0..129b9104d385499e8443b4fc45dcf6c2e26497e8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -10760,7 +10760,7 @@ fn finishSwitchBr( .@"enum" => if (else_is_named_only or !item_ty.isNonexhaustiveEnum(zcu) or tagged_union_originally) { - try branch_hints.ensureUnusedCapacity(gpa, @intCast(validated_switch.seen_enum_fields.len)); + try branch_hints.ensureUnusedCapacity(gpa, @intCast(validated_switch.seen.enum_fields.len)); break :check_enumerable .{ undefined, undefined }; }, .error_set => if (!operand_ty.isAnyError(zcu)) { @@ -10881,13 +10881,13 @@ fn finishSwitchBr( try branch_hints.append(gpa, prong_hint); try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len + - (validated_switch.seen_enum_fields.len + 1 - zir_switch.totalItemsLen()) + // +1 because totalItemsLen includes the _ + (validated_switch.seen.enum_fields.len + 1 - zir_switch.totalItemsLen()) + // +1 because totalItemsLen includes the _ case_block.instructions.items.len); const extra_case = cases_extra.addManyAsArrayAssumeCapacity( @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len, ); var items_len: u32 = 0; - for (validated_switch.seen_enum_fields, 0..) |seen_field, field_i| { + for (validated_switch.seen.enum_fields, 0..) |seen_field, field_i| { if (seen_field != null) continue; const item_val = try pt.enumValueFieldIndex(item_ty, @intCast(field_i)); const item_ref: Air.Inst.Ref = .fromValue(item_val); @@ -10920,7 +10920,7 @@ fn finishSwitchBr( } if (tagged_union_originally) { const union_obj = zcu.typeToUnion(operand_ty).?; - for (validated_switch.seen_enum_fields, 0..) |seen_field, field_i| { + for (validated_switch.seen.enum_fields, 0..) |seen_field, field_i| { if (seen_field != null) continue; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_i]); if (!field_ty.isNoReturn(zcu)) break :analyze_body true; @@ -11004,17 +11004,21 @@ fn finishSwitchBr( } const ValidatedSwitchBlock = struct { - seen_enum_fields: []const ?LazySrcLoc, - seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), - seen_ranges: std.MultiArrayList(RangeSet.Range).Slice, - true_src: ?LazySrcLoc, - false_src: ?LazySrcLoc, - void_src: ?LazySrcLoc, - + seen: Seen, case_vals: []const Air.Inst.Ref, else_case: Zir.UnwrappedSwitchBlock.Case.Else, else_err_ty: ?Type, + const Seen = struct { + enum_fields: []?LazySrcLoc, + errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), + sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc), + ranges: RangeSet, + true_src: ?LazySrcLoc, + false_src: ?LazySrcLoc, + void_src: ?LazySrcLoc, + }; + fn iterateUnhandledItems( validated_switch: *const ValidatedSwitchBlock, /// May be `undefined` if `item_ty` isn't an `error_set`. @@ -11023,28 +11027,26 @@ const ValidatedSwitchBlock = struct { min_int: Value, ) UnhandledIterator { return .{ + .error_names = error_names, + .seen = &validated_switch.seen, + .next_idx = 0, .next_val = min_int, - .error_names = error_names, - .seen_enum_fields = validated_switch.seen_enum_fields, - .seen_errors = &validated_switch.seen_errors, - .seen_ranges = validated_switch.seen_ranges, - .seen_true = validated_switch.true_src != null, - .seen_false = validated_switch.false_src != null, - .seen_void = validated_switch.void_src != null, + .handled_true = validated_switch.seen.true_src != null, + .handled_false = validated_switch.seen.false_src != null, + .handled_void = validated_switch.seen.void_src != null, }; } const UnhandledIterator = struct { + error_names: InternPool.NullTerminatedString.Slice, + seen: *const Seen, + next_idx: u32, next_val: ?Value, - error_names: InternPool.NullTerminatedString.Slice, - seen_enum_fields: []const ?LazySrcLoc, - seen_errors: *const std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), - seen_ranges: std.MultiArrayList(RangeSet.Range).Slice, - seen_true: bool, - seen_false: bool, - seen_void: bool, + handled_true: bool, + handled_false: bool, + handled_void: bool, fn next(it: *UnhandledIterator, sema: *Sema, item_ty: Type) CompileError!?Value { const pt = sema.pt; @@ -11052,7 +11054,7 @@ const ValidatedSwitchBlock = struct { const ip = &zcu.intern_pool; switch (item_ty.zigTypeTag(zcu)) { .@"enum" => { - for (it.seen_enum_fields[it.next_idx..], it.next_idx..) |seen_field, field_i| { + for (it.seen.enum_fields[it.next_idx..], it.next_idx..) |seen_field, field_i| { if (seen_field != null) continue; it.next_idx = @intCast(field_i + 1); return try pt.enumValueFieldIndex(item_ty, @intCast(field_i)); @@ -11061,7 +11063,7 @@ const ValidatedSwitchBlock = struct { }, .error_set => { for (it.error_names.get(ip)[it.next_idx..], it.next_idx..) |err_name, name_i| { - if (it.seen_errors.contains(err_name)) continue; + if (it.seen.errors.contains(err_name)) continue; it.next_idx = @intCast(name_i + 1); return .fromInterned(try pt.intern(.{ .err = .{ .ty = item_ty.toIntern(), @@ -11077,14 +11079,14 @@ const ValidatedSwitchBlock = struct { .@"union", .@"struct" => item_ty.backingIntType(zcu), else => unreachable, }; - while (it.next_idx < it.seen_ranges.len and - cur_val.eql(it.seen_ranges.items(.first)[it.next_idx], int_ty, zcu)) + while (it.next_idx < it.seen.ranges.list.len and + cur_val.eql(it.seen.ranges.list.items(.first)[it.next_idx], int_ty, zcu)) { defer it.next_idx += 1; const incr = try arith.incrementDefinedInt( sema, int_ty, - it.seen_ranges.items(.last)[it.next_idx], + it.seen.ranges.list.items(.last)[it.next_idx], ); if (incr.overflow) { it.next_val = null; @@ -11101,19 +11103,19 @@ const ValidatedSwitchBlock = struct { }; }, .bool => { - if (!it.seen_true) { - it.seen_true = true; + if (!it.handled_true) { + it.handled_true = true; return .true; } - if (!it.seen_false) { - it.seen_false = true; + if (!it.handled_false) { + it.handled_false = true; return .false; } return null; }, .void => { - if (!it.seen_void) { - it.seen_void = true; + if (!it.handled_void) { + it.handled_void = true; return .void; } return null; @@ -11267,13 +11269,15 @@ fn validateSwitchBlock( var case_vals: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, zir_switch.item_infos.len); // Duplicate checking variables later also used for `inline else`. - var seen_enum_fields: []?LazySrcLoc = &.{}; - var seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc) = .empty; - var seen_sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc) = .empty; - var range_set: RangeSet = .empty; - var true_src: ?LazySrcLoc = null; - var false_src: ?LazySrcLoc = null; - var void_src: ?LazySrcLoc = null; + var seen: ValidatedSwitchBlock.Seen = .{ + .enum_fields = &.{}, + .errors = .empty, + .sparse_values = .empty, + .ranges = .empty, + .true_src = null, + .false_src = null, + .void_src = null, + }; var else_err_ty: ?Type = null; @@ -11281,20 +11285,20 @@ fn validateSwitchBlock( switch (item_ty.zigTypeTag(zcu)) { .@"enum" => { - seen_enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu)); - @memset(seen_enum_fields, null); - // `range_set` is used for non-exhaustive enum values that do not + seen.enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu)); + @memset(seen.enum_fields, null); + // `seen.ranges` is used for non-exhaustive enum values that do not // correspond to any tags. Since this is rare, we only allocate on // demand in `validateSwitchItem`. }, .error_set => { - try seen_errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); + try seen.errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); }, .int, .comptime_int, .@"union", .@"struct" => { - try range_set.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); + try seen.ranges.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); }, .enum_literal, .@"fn", .pointer, .type => { - try seen_sparse_values.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); + try seen.sparse_values.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); }, .bool, .void => {}, @@ -11337,7 +11341,7 @@ fn validateSwitchBlock( case_vals.appendAssumeCapacity(.none); } else { const item, extra_index = try sema.resolveSwitchItem(block, item_src, item_ty, item_info, extra_index, switch_inst, prong_info.is_comptime_unreach); - try sema.validateSwitchItemOrRange(block, item_src, item.val, null, item_ty, seen_enum_fields, &seen_errors, &seen_sparse_values, &range_set, &true_src, &false_src, &void_src); + try sema.validateSwitchItemOrRange(block, item_src, item.val, null, item_ty, &seen); case_vals.appendAssumeCapacity(item.ref); } } @@ -11352,7 +11356,7 @@ fn validateSwitchBlock( const last_src = block.src(.{ .switch_case_item_range_last = range_offset }); const first_item, extra_index = try sema.resolveSwitchItem(block, first_src, item_ty, range_info[0], extra_index, switch_inst, prong_info.is_comptime_unreach); const last_item, extra_index = try sema.resolveSwitchItem(block, last_src, item_ty, range_info[1], extra_index, switch_inst, prong_info.is_comptime_unreach); - try sema.validateSwitchItemOrRange(block, range_src, first_item.val, last_item.val, item_ty, seen_enum_fields, &seen_errors, &seen_sparse_values, &range_set, &true_src, &false_src, &void_src); + try sema.validateSwitchItemOrRange(block, range_src, first_item.val, last_item.val, item_ty, &seen); case_vals.appendSliceAssumeCapacity(&.{ first_item.ref, last_item.ref }); } } @@ -11383,7 +11387,7 @@ fn validateSwitchBlock( // Validate for missing special prongs. switch (item_ty.zigTypeTag(zcu)) { .@"enum" => { - const all_tags_handled = for (seen_enum_fields) |seen_src| { + const all_tags_handled = for (seen.enum_fields) |seen_src| { if (seen_src == null) break false; } else true; @@ -11411,7 +11415,7 @@ fn validateSwitchBlock( .{}, ); errdefer msg.destroy(sema.gpa); - for (seen_enum_fields, 0..) |seen_src, i| { + for (seen.enum_fields, 0..) |seen_src, i| { if (seen_src != null) continue; const field_name = item_ty.enumFieldName(i, zcu); @@ -11463,7 +11467,7 @@ fn validateSwitchBlock( var seen_errors_from_set: u32 = 0; for (error_names.get(ip)) |error_name| { - if (seen_errors.contains(error_name)) { + if (seen.errors.contains(error_name)) { seen_errors_from_set += 1; } else if (!has_else) { const msg = maybe_msg orelse blk: { @@ -11505,7 +11509,7 @@ fn validateSwitchBlock( var names: InferredErrorSet.NameMap = .{}; try names.ensureUnusedCapacity(sema.arena, error_names.len); for (error_names.get(ip)) |error_name| { - if (seen_errors.contains(error_name)) continue; + if (seen.errors.contains(error_name)) continue; names.putAssumeCapacityNoClobber(error_name, {}); } // No need to keep the hash map metadata correct; here we @@ -11523,7 +11527,7 @@ fn validateSwitchBlock( }; const min_int = try int_ty.minInt(pt, int_ty); const max_int = try int_ty.maxInt(pt, int_ty); - if (try range_set.spans(arena, min_int, max_int, int_ty, zcu)) { + if (try seen.ranges.spans(arena, min_int, max_int, int_ty, zcu)) { if (has_else) { return sema.fail( block, @@ -11556,8 +11560,8 @@ fn validateSwitchBlock( }, .bool, .void => |type_tag| { const all_values_handled = switch (type_tag) { - .bool => true_src != null and false_src != null, - .void => void_src != null, + .bool => seen.true_src != null and seen.false_src != null, + .void => seen.void_src != null, else => unreachable, }; if (has_else) { @@ -11584,13 +11588,7 @@ fn validateSwitchBlock( } return .{ - .seen_enum_fields = seen_enum_fields, - .seen_errors = seen_errors, - .seen_ranges = range_set.ranges.slice(), - .true_src = true_src, - .false_src = false_src, - .void_src = void_src, - + .seen = seen, .case_vals = case_vals.items, .else_case = else_case, .else_err_ty = else_err_ty, @@ -11768,7 +11766,7 @@ fn resolveSwitchBlock( .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline }; if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref); if (tagged_union_originally) { - for (validated_switch.seen_enum_fields, 0..) |maybe_seen, field_i| { + for (validated_switch.seen.enum_fields, 0..) |maybe_seen, field_i| { if (maybe_seen != null) continue; if (!operand_ty.unionFieldTypeByIndex(field_i, zcu).isNoReturn(zcu)) break; } else { @@ -12573,13 +12571,7 @@ fn validateSwitchItemOrRange( item_val: Value, opt_last_val: ?Value, item_ty: Type, - seen_enum_fields: []?LazySrcLoc, - seen_errors: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), - seen_sparse_values: *std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc), - range_set: *RangeSet, - true_src: *?LazySrcLoc, - false_src: *?LazySrcLoc, - void_src: *?LazySrcLoc, + seen: *ValidatedSwitchBlock.Seen, ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; @@ -12588,88 +12580,117 @@ fn validateSwitchItemOrRange( .@"enum" => { const int = ip.indexToKey(item_val.toIntern()).enum_tag.int; if (ip.loadEnumType(item_ty.toIntern()).tagValueIndex(ip, int)) |field_index| { - const maybe_prev_src = seen_enum_fields[field_index]; - seen_enum_fields[field_index] = item_src; + const maybe_prev_src = seen.enum_fields[field_index]; + seen.enum_fields[field_index] = item_src; break :maybe_prev_src maybe_prev_src; } else { - break :maybe_prev_src try range_set.add(sema.arena, .{ + try seen.ranges.ensureUnusedCapacity(sema.arena, 1); + break :maybe_prev_src if (seen.ranges.addAssumeCapacity(.{ .first = .fromInterned(int), .last = .fromInterned(int), .src = item_src, - }, .fromInterned(ip.typeOf(int)), zcu); + }, .fromInterned(ip.typeOf(int)), zcu)) |prev| prev.src else null; } }, .error_set => { const error_name = ip.indexToKey(item_val.toIntern()).err.name; - break :maybe_prev_src if (seen_errors.fetchPutAssumeCapacity(error_name, item_src)) |prev| + break :maybe_prev_src if (seen.errors.fetchPutAssumeCapacity(error_name, item_src)) |prev| prev.value else null; }, .int, .comptime_int => { - if (opt_last_val) |last_val| { - const first_val = item_val; + const first_val = item_val; + const last_val: Value = last_val: { + const last_val = opt_last_val orelse break :last_val item_val; if (try first_val.compareAll(.gt, last_val, item_ty, pt)) { return sema.fail(block, item_src, "range start value is greater than the end value", .{}); } - break :maybe_prev_src range_set.addAssumeCapacity(.{ - .first = first_val, - .last = last_val, - .src = item_src, - }, item_ty, zcu); - } else { - break :maybe_prev_src range_set.addAssumeCapacity(.{ - .first = item_val, - .last = item_val, - .src = item_src, - }, item_ty, zcu); + break :last_val last_val; + }; + if (seen.ranges.addAssumeCapacity(.{ + .first = first_val, + .last = last_val, + .src = item_src, + }, item_ty, zcu)) |prev_range| { + const overlap_start = first_val.numberMax(prev_range.first, zcu); + const overlap_end = last_val.numberMin(prev_range.last, zcu); + if (overlap_start.eql(overlap_end, item_ty, zcu)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{ + overlap_start.fmtValueSema(pt, sema), + }); + errdefer msg.destroy(sema.gpa); + if (prev_range.first.eql(prev_range.last, item_ty, zcu)) { + try sema.errNote(prev_range.src, msg, "previous value here", .{}); + } else { + try sema.errNote(prev_range.src, msg, "previous value inside range here", .{}); + } + break :msg msg; + }); + } + assert(!prev_range.first.eql(prev_range.last, item_ty, zcu)); + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(item_src, "duplicate switch ranges", .{}); + errdefer msg.destroy(sema.gpa); + if (first_val.eql(prev_range.first, item_ty, zcu) and + last_val.eql(prev_range.last, item_ty, zcu)) + { + try sema.errNote(prev_range.src, msg, "previous range here", .{}); + } else { + try sema.errNote(prev_range.src, msg, "overlaps with previous range here", .{}); + try sema.errNote(prev_range.src, msg, "ranges overlap from '{f}' to '{f}'", .{ + overlap_start.fmtValueSema(pt, sema), overlap_end.fmtValueSema(pt, sema), + }); + } + break :msg msg; + }); } + break :maybe_prev_src null; }, .@"union", .@"struct" => { const backing_int_val = ip.indexToKey(item_val.toIntern()).bitpack.backing_int_val; - break :maybe_prev_src range_set.addAssumeCapacity(.{ + break :maybe_prev_src if (seen.ranges.addAssumeCapacity(.{ .first = .fromInterned(backing_int_val), .last = .fromInterned(backing_int_val), .src = item_src, - }, item_ty.backingIntType(zcu), zcu); + }, item_ty.backingIntType(zcu), zcu)) |prev| prev.src else null; }, .enum_literal, .@"fn", .pointer, .type => { - break :maybe_prev_src if (seen_sparse_values.fetchPutAssumeCapacity(item_val.toIntern(), item_src)) |prev| + break :maybe_prev_src if (seen.sparse_values.fetchPutAssumeCapacity(item_val.toIntern(), item_src)) |prev| prev.value else null; }, .bool => { if (item_val.toBool()) { - if (true_src.*) |prev_src| break :maybe_prev_src prev_src; - true_src.* = item_src; + if (seen.true_src) |prev_src| break :maybe_prev_src prev_src; + seen.true_src = item_src; } else { - if (false_src.*) |prev_src| break :maybe_prev_src prev_src; - false_src.* = item_src; + if (seen.false_src) |prev_src| break :maybe_prev_src prev_src; + seen.false_src = item_src; } break :maybe_prev_src null; }, .void => { - if (void_src.*) |prev_src| break :maybe_prev_src prev_src; - void_src.* = item_src; + if (seen.void_src) |prev_src| break :maybe_prev_src prev_src; + seen.void_src = item_src; break :maybe_prev_src null; }, else => unreachable, // should have already checked for invalid types }; if (maybe_prev_src) |prev_src| { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg( - item_src, - "duplicate switch value", - .{}, - ); + const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{ + item_val.fmtValueSema(pt, sema), + }); errdefer msg.destroy(sema.gpa); - try sema.errNote( - prev_src, - msg, - "previous value here", - .{}, - ); + try sema.errNote(prev_src, msg, "previous value here", .{}); + if (item_ty.zigTypeTag(zcu) == .type) { + try sema.addDeclaredHereNote(msg, item_val.toType()); + } else { + try sema.addDeclaredHereNote(msg, item_ty); + } break :msg msg; }); } diff --git a/test/cases/compile_errors/duplicate_boolean_switch_value.zig b/test/cases/compile_errors/duplicate_boolean_switch_value.zig index d3b7dba6e88e77e75b01861d691d02da4f9847e6..700851ec77b1c9dc6d10eb0cd9f37f1aa0a69bcb 100644 --- a/test/cases/compile_errors/duplicate_boolean_switch_value.zig +++ b/test/cases/compile_errors/duplicate_boolean_switch_value.zig @@ -17,7 +17,7 @@ comptime { // error // -// :5:9: error: duplicate switch value +// :5:9: error: duplicate switch value 'true' // :3:9: note: previous value here -// :13:9: error: duplicate switch value +// :13:9: error: duplicate switch value 'false' // :11:9: note: previous value here diff --git a/test/cases/compile_errors/duplicate_error_in_switch.zig b/test/cases/compile_errors/duplicate_error_in_switch.zig index 91f6f13c7ea158195da1aa16993f7982f9ef010f..6a2da7672e1d0851b975858e414c333313fb93fd 100644 --- a/test/cases/compile_errors/duplicate_error_in_switch.zig +++ b/test/cases/compile_errors/duplicate_error_in_switch.zig @@ -16,5 +16,5 @@ fn foo(x: i32) !void { // error // -// :5:9: error: duplicate switch value +// :5:9: error: duplicate switch value 'error.Foo' // :3:9: note: previous value here diff --git a/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong.zig b/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong.zig index 754451321c91d75d0d465e18d475ff08bae9865a..5c69bd922f2011cc900c50e891e4ee387a49b47f 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong.zig @@ -20,5 +20,6 @@ export fn entry() usize { // error // -// :13:15: error: duplicate switch value +// :13:15: error: duplicate switch value '.Two' // :10:15: note: previous value here +// :1:16: note: enum declared here diff --git a/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong_when_else_present.zig b/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong_when_else_present.zig index 3cba599968fd15a1abdc9b64e1fd4fb984bd363b..24627b6282194defe031d9db2693026b8c381984 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong_when_else_present.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_enumeration_prong_when_else_present.zig @@ -21,5 +21,6 @@ export fn entry() usize { // error // -// :13:15: error: duplicate switch value +// :13:15: error: duplicate switch value '.Two' // :10:15: note: previous value here +// :1:16: note: enum declared here diff --git a/test/cases/compile_errors/switch_expression-duplicate_error_prong.zig b/test/cases/compile_errors/switch_expression-duplicate_error_prong.zig index 1ee6add616cc0c0546a0b9f3833ed13072eb0d65..3df559cf03a73bae9f06d6c84642952e805a1a5e 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_error_prong.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_error_prong.zig @@ -25,7 +25,7 @@ export fn entry() usize { // error // -// :8:9: error: duplicate switch value +// :8:9: error: duplicate switch value 'error.Foo' // :5:9: note: previous value here -// :16:9: error: duplicate switch value +// :16:9: error: duplicate switch value 'error.Foo' // :13:9: note: previous value here diff --git a/test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig b/test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig index 38ae0099b3e4a240a4bd8940e472b5d64985089f..d21e144704131ac2b6921e7cc0337c053487b96f 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_error_prong_when_else_present.zig @@ -27,7 +27,7 @@ export fn entry() usize { // error // -// :8:9: error: duplicate switch value +// :8:9: error: duplicate switch value 'error.Foo' // :5:9: note: previous value here -// :17:9: error: duplicate switch value +// :17:9: error: duplicate switch value 'error.Foo' // :14:9: note: previous value here diff --git a/test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig b/test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig deleted file mode 100644 index d970393450d1399b985ead356f5f21a138561850..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig +++ /dev/null @@ -1,16 +0,0 @@ -fn foo(x: u8) u8 { - return switch (x) { - 0...100 => @as(u8, 0), - 101...200 => 1, - 201, 203...207 => 2, - 206...255 => 3, - }; -} -export fn entry() usize { - return @sizeOf(@TypeOf(&foo)); -} - -// error -// -// :6:12: error: duplicate switch value -// :5:17: note: previous value here diff --git a/test/cases/compile_errors/switch_expression-duplicate_type.zig b/test/cases/compile_errors/switch_expression-duplicate_type.zig index 4b553989808cb04e52dba2b2207bced6b8f090bc..7b8f277480b71bf708eba135896f5d61f48ad1b5 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_type.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_type.zig @@ -13,5 +13,5 @@ export fn entry() usize { // error // -// :6:9: error: duplicate switch value +// :6:9: error: duplicate switch value 'u32' // :4:9: note: previous value here diff --git a/test/cases/compile_errors/switch_expression-duplicate_type_struct_alias.zig b/test/cases/compile_errors/switch_expression-duplicate_type_struct_alias.zig index 0b67e2107d452df6a4e19a11a3ed7d8f6c8e6f64..f2919239c82c3a68d459b686c33a35f027f36f32 100644 --- a/test/cases/compile_errors/switch_expression-duplicate_type_struct_alias.zig +++ b/test/cases/compile_errors/switch_expression-duplicate_type_struct_alias.zig @@ -17,5 +17,6 @@ export fn entry() usize { // error // -// :10:9: error: duplicate switch value +// :10:9: error: duplicate switch value 'tmp.Test' // :8:9: note: previous value here +// :1:14: note: struct declared here diff --git a/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig b/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig index 619875c7970ba869cb84ac43cdd1f0789724ec4f..6d7ffc0e1c9728c0c9ea5ac788263945d156c823 100644 --- a/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig +++ b/test/cases/compile_errors/switch_with_overlapping_case_ranges.zig @@ -28,13 +28,43 @@ export fn entry4(x: u8) void { } } +export fn entry5(x: u8) void { + switch (x) { + 0...255 => {}, + 4...120 => {}, + } +} + +export fn entry6(x: u8) void { + switch (x) { + 0...130 => {}, + 120...255 => {}, + } +} + +export fn entry7(x: u8) void { + switch (x) { + 2 => {}, + 0...255 => {}, + } +} + // error // -// :4:10: error: duplicate switch value -// :3:10: note: previous value here -// :11:10: error: duplicate switch value -// :10:13: note: previous value here -// :17:10: error: duplicate switch value +// :4:10: error: duplicate switch ranges +// :3:10: note: overlaps with previous range here +// :3:10: note: ranges overlap from '1' to '2' +// :11:10: error: duplicate switch value '5' +// :10:13: note: previous value inside range here +// :17:10: error: duplicate switch value '5' // :18:9: note: previous value here -// :27:10: error: duplicate switch value +// :27:10: error: duplicate switch value '6' // :26:9: note: previous value here +// :34:10: error: duplicate switch ranges +// :33:10: note: overlaps with previous range here +// :33:10: note: ranges overlap from '4' to '120' +// :41:12: error: duplicate switch ranges +// :40:10: note: overlaps with previous range here +// :40:10: note: ranges overlap from '120' to '130' +// :48:10: error: duplicate switch value '2' +// :47:9: note: previous value here -- 2.54.0 From 2ae38cbd2599af06beebc4ae9e3cdbbbc6cefc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 25 Jul 2026 01:15:36 +0200 Subject: [PATCH 034/215] std.macho: add encryption_info_command[_64] --- lib/std/macho.zig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/std/macho.zig b/lib/std/macho.zig index 9fdce9dd6605f450ab7eb9fee2b19b4f3787783d..48804cf7b1ccb51e8a37052686d0a9afe670d116 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -588,6 +588,25 @@ pub const rpath_command = extern struct { path: u32, }; +pub const encryption_info_command = extern struct { + cmd: LC = .ENCRYPTION_INFO, + cmdsize: u32 = @sizeOf(encryption_info_command), + + cryptoff: u32, + cryptsize: u32, + cryptid: u32 = 0, +}; + +pub const encryption_info_command_64 = extern struct { + cmd: LC = .ENCRYPTION_INFO_64, + cmdsize: u32 = @sizeOf(encryption_info_command_64), + + cryptoff: u32, + cryptsize: u32, + cryptid: u32 = 0, + _pad: u32 = 0, +}; + /// The segment load command indicates that a part of this file is to be /// mapped into the task's address space. The size of this segment in memory, /// vmsize, maybe equal to or larger than the amount to map from this file, -- 2.54.0 From 72e09893686613bd65369faf9272171d272fbee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 25 Jul 2026 01:16:19 +0200 Subject: [PATCH 035/215] link.MachO: add LC_ENCRYPTION_INFO_64 for non-sim ios/tvos/visionos/watchos closes https://codeberg.org/ziglang/zig/issues/36285 --- src/link/MachO.zig | 26 +++++++++++++++++++++++--- src/link/MachO/load_commands.zig | 27 ++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 543d803b11286b8a22155ba80d785012d9f49363..77441748d57ef2ad1823f01d2bad18c3b9c1a5e5 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty, segments: std.ArrayList(macho.segment_command_64) = .empty, sections: std.MultiArrayList(Section) = .{}, +/// Populated by `allocateSections`. +header_size: ?u32 = null, resolver: SymbolResolver = .{}, /// This table will be populated after `scanRelocs` has run. @@ -2209,13 +2211,14 @@ fn initSegments(self: *MachO) !void { } fn allocateSections(self: *MachO) !void { - const headerpad = try load_commands.calcMinHeaderPadSize(self); + const header_size = try load_commands.calcMinHeaderSize(self); + self.header_size = header_size; var vmaddr: u64 = if (self.pagezero_seg_index) |index| self.segments.items[index].vmaddr + self.segments.items[index].vmsize else 0; - vmaddr += headerpad; - var fileoff = headerpad; + vmaddr += header_size; + var fileoff = header_size; var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; const page_size = self.getPageSize(); @@ -2895,6 +2898,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { ncmds += 1; } + if (self.needsEncryptionInfo()) { + try load_commands.writeEncryptionInfoLC(self, &writer); + ncmds += 1; + } + for (self.rpath_list) |rpath| { try load_commands.writeRpathLC(rpath, &writer); ncmds += 1; @@ -5410,6 +5418,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 { return result; } +pub fn needsEncryptionInfo(macho_file: *MachO) bool { + const target = macho_file.getTarget(); + return switch (target.os.tag) { + .ios, + .tvos, + .visionos, + .watchos, + => target.abi != .simulator, + else => false, + }; +} + /// Branch instruction has 26 bits immediate but is 4 byte aligned. const jump_bits = @bitSizeOf(i28); const max_distance = (1 << (jump_bits - 1)); diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index ec556b16bb9a7a50ada47fe9740c25aea9fc775b..62bbc751cb58e82aee019f07065eabf1b8cf8917 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -62,6 +62,10 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 assume_max_path_len, ); } + // LC_ENCRYPTION_INFO_64 + if (macho_file.needsEncryptionInfo()) { + sizeofcmds += @sizeOf(macho.encryption_info_command_64); + } // LC_RPATH { for (macho_file.rpath_list) |rpath| { @@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { return @as(u32, @intCast(sizeofcmds)); } -pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { +pub fn calcMinHeaderSize(macho_file: *MachO) !u32 { var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) + (macho_file.headerpad_size orelse MachO.default_headerpad_size); - log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)}); + log.debug("minimum requested header + padding size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)}); if (macho_file.headerpad_max_install_names) { const min_headerpad_size: u32 = try calcLoadCommandsSize(macho_file, true); - log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{ + log.debug("headerpad_max_install_names minimum header + padding size 0x{x}", .{ min_headerpad_size + @sizeOf(macho.mach_header_64), }); padding = @max(padding, min_headerpad_size); } const offset = @sizeOf(macho.mach_header_64) + padding; - log.debug("actual headerpad size 0x{x}", .{offset}); + log.debug("actual header + padding size 0x{x}", .{offset}); - return offset; + // Encryption is done at page granularity, so if the output needs a load + // command for encryption info, ensure that the header + load commands have + // at least one full, unencrypted page. + return if (macho_file.needsEncryptionInfo()) + mem.alignForward(u32, offset, macho_file.getPageSize()) + else + offset; } pub fn writeDylinkerLC(writer: *Writer) !void { @@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { }, writer); } +pub fn writeEncryptionInfoLC(macho_file: *MachO, writer: *Writer) !void { + try writer.writeAll(mem.asBytes(&macho.encryption_info_command_64{ + .cryptoff = macho_file.header_size.?, + .cryptsize = @as(u32, @intCast(macho_file.getTextSegment().filesize)) - macho_file.header_size.?, + })); +} + pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { const rpath_len = rpath.len + 1; const cmdsize = @as(u32, @intCast(mem.alignForward( -- 2.54.0 From ff10b90bc50e1e2792bac513a4ba76f7696b4dca Mon Sep 17 00:00:00 2001 From: Pavel Verigo Date: Sat, 25 Jul 2026 16:30:29 +0200 Subject: [PATCH 036/215] stage2-wasm: fix sleb/uleb confusion in emit --- src/codegen/wasm/Emit.zig | 4 ++-- src/link/Wasm/Flush.zig | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/codegen/wasm/Emit.zig b/src/codegen/wasm/Emit.zig index 81bf1e1315362d5b4dd4928b29f76dc5ab1f41f0..ccc75b9b536871e5010f1a5155cdd0ae4abf9301 100644 --- a/src/codegen/wasm/Emit.zig +++ b/src/codegen/wasm/Emit.zig @@ -978,7 +978,7 @@ fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: code.appendAssumeCapacity(@backingInt(opcode)); const addr = wasm.uavAddr(value); - writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + offset))); + writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + offset))); } fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: bool) !void { @@ -1004,7 +1004,7 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); } else { const addr = wasm.navAddr(data.nav_index); - writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); + writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); } } diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 410ebb7e4434595ecbe1353810235ad1f6b468b2..ac580f9bbc5656362185489f457f15b387605a68 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -2032,8 +2032,7 @@ fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Al try bytes.ensureUnusedCapacity(gpa, 9); bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32)); bytes.appendAssumeCapacity(mutable); - bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); - appendReservedUleb32(bytes, val); + appendReservedI32Const(bytes, val); bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); } -- 2.54.0 From d552433946de375430a339e245b5ea0af1b79ca6 Mon Sep 17 00:00:00 2001 From: zacoons Date: Sun, 26 Jul 2026 12:46:04 +1000 Subject: [PATCH 037/215] std.process: add missing io parameters in getUserInfo --- lib/std/process.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index 33adef9e29fa5444df291db23aec45045b65d4e2..3e6f62b2c386a6d721b68cc44b12f26133c912fd 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -100,7 +100,7 @@ pub const UserInfo = struct { }; /// POSIX function which gets a uid from username. -pub fn getUserInfo(name: []const u8) !UserInfo { +pub fn getUserInfo(io: Io, name: []const u8) !UserInfo { return switch (native_os) { .linux, .driverkit, @@ -116,7 +116,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo { .haiku, .illumos, .serenity, - => posixGetUserInfo(name), + => posixGetUserInfo(io, name), else => @compileError("Unsupported OS"), }; } @@ -127,7 +127,7 @@ pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo { const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{}); defer file.close(io); var buffer: [4096]u8 = undefined; - var file_reader = file.reader(&buffer); + var file_reader = file.reader(io, &buffer); return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) { error.ReadFailed => return file_reader.err.?, error.EndOfStream => return error.UserNotFound, -- 2.54.0 From 2aa8f3d3f5bf98d1a6a7396c608e24203cf094be Mon Sep 17 00:00:00 2001 From: Kleshzz Date: Thu, 23 Jul 2026 15:05:18 +0300 Subject: [PATCH 038/215] spirv: improve assembler capacity allocation, error locations --- src/codegen/spirv/Assembler.zig | 42 +++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index 5da442650eb089ecb89e68e9f9ffc21551adcf21..6a96b5e3a00445176a67e085a0ca27cbd2f88dd3 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -26,7 +26,7 @@ inst: struct { string_bytes: std.ArrayList(u8) = .empty, inst_offset: u32 = 0, - fn result(ass: @This()) ?AsmValue.Ref { + fn result(ass: *const @This()) ?AsmValue.Ref { for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| { switch (op) { .result_id => |index| return index, @@ -179,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void { const cg = ass.cg; const result: AsmValue = switch (ass.inst.opcode) { .OpEntryPoint => { - return ass.fail(ass.currentToken().start, "cannot export entry points in assembly", .{}); + return ass.fail(ass.inst.inst_offset, "cannot export entry points in assembly", .{}); }, .OpExecutionMode, .OpExecutionModeId => { - return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{}); + return ass.fail(ass.inst.inst_offset, "cannot set execution mode in assembly", .{}); }, .OpCapability, .OpExtension => { - return ass.fail(ass.currentToken().start, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{}); + return ass.fail(ass.inst.inst_offset, "cannot declare capabilities or extensions in assembly; use -mcpu instead", .{}); }, .OpExtInstImport => blk: { const set_name_offset = ass.inst.operands.items[1].string; const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0); const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse { - return ass.fail(set_name_offset, "unknown instruction set: {s}", .{set_name}); + return ass.fail(ass.inst.inst_offset, "unknown instruction set: {s}", .{set_name}); }; break :blk .{ .value = try cg.importInstructionSet(set_tag) }; }, @@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue { var maybe_result_id: ?Id = null; const first_word = section.instructions.items.len; - // At this point we're not quite sure how many operands this instruction is - // going to have, so insert 0 and patch up the actual opcode word later. - try section.ensureUnusedCapacity(cg.gpa, 1); + + // Pre-calculate exact instruction size to avoid per-operand capacity checks. + var total_words: usize = 1; // 1 word for the opcode itself + for (operands) |operand| { + total_words += switch (operand) { + .value, .literal32, .result_id, .ref_id => 1, + .literal64 => 2, + .string => |offset| blk: { + const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0); + break :blk @divCeil(text.len + 1, @sizeOf(Word)); + }, + }; + } + + try section.ensureUnusedCapacity(cg.gpa, total_words); section.writeWord(0); for (operands) |operand| { switch (operand) { - .value, .literal32 => |word| { - try section.ensureUnusedCapacity(cg.gpa, 1); - section.writeWord(word); - }, - .literal64 => |dword| { - try section.ensureUnusedCapacity(cg.gpa, 2); - section.writeDoubleWord(dword); - }, + .value, .literal32 => |word| section.writeWord(word), + .literal64 => |dword| section.writeDoubleWord(dword), .result_id => { maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index| cg.declPtr(spv_decl_index).result_id else cg.allocId(); - try section.ensureUnusedCapacity(cg.gpa, 1); section.writeOperand(Id, maybe_result_id.?); }, .ref_id => |index| { const result = try ass.resolveRef(index); - try section.ensureUnusedCapacity(cg.gpa, 1); section.writeOperand(spec.Id, result.resultId()); }, .string => |offset| { const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0); - const size = @divCeil(text.len + 1, @sizeOf(Word)); - try section.ensureUnusedCapacity(cg.gpa, size); section.writeOperand(spec.LiteralString, text); }, } -- 2.54.0 From 39c5d3a205b8fb2bf21d49c71c8c30ce15d73254 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 23 Jul 2026 21:52:17 -0400 Subject: [PATCH 039/215] Elf2: start implementing archives Allows building static libraries with the new linker. --- lib/std/elf.zig | 8 +- src/link/Elf2.zig | 662 +++++++++++++++++++++++++++------------- src/link/MappedFile.zig | 134 +++++--- 3 files changed, 549 insertions(+), 255 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 294bde804cae719605bd9af7e65299a5b7185a05..e96cb50f97512239ff86e648d4dabd91eb5f01e4 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -3272,12 +3272,12 @@ pub const ar_hdr = extern struct { ar_fmag: [2]u8, pub fn date(self: ar_hdr) std.fmt.ParseIntError!u64 { - const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{0x20}); + const value = mem.trimEnd(u8, &self.ar_date, " "); return std.fmt.parseInt(u64, value, 10); } pub fn size(self: ar_hdr) std.fmt.ParseIntError!u32 { - const value = mem.trimEnd(u8, &self.ar_size, &[_]u8{0x20}); + const value = mem.trimEnd(u8, &self.ar_size, " "); return std.fmt.parseInt(u32, value, 10); } @@ -3311,7 +3311,7 @@ pub const ar_hdr = extern struct { pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?u32 { const value = &self.ar_name; if (value[0] != '/') return null; - const trimmed = mem.trimEnd(u8, value, &[_]u8{0x20}); + const trimmed = mem.trimEnd(u8, value, " "); return try std.fmt.parseInt(u32, trimmed[1..], 10); } }; @@ -3319,7 +3319,7 @@ pub const ar_hdr = extern struct { fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 { assert(name.len <= 16); const padding = 16 - name.len; - return name ++ @as([padding]u8, @splat(0x20)); + return name ++ @as([padding]u8, @splat(' ')); } // Archive files start with the ARMAG identifying string. Then follows a diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 71298617402c6a939aea5f13a71ba205789e3e18..be921d285bf96e557a24a04ed53a3f84052bfa2a 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -126,8 +126,14 @@ needed: std.array_hash_map.Auto(String(.dynstr), void), inputs: std.ArrayList(struct { path: std.Build.Cache.Path, member: ?[]const u8, - file_symbol: Symbol.LocalIndex, + extra: union { + /// Active for static libraries. + node: MappedFile.Node.Index, + /// Active otherwise. + file_symbol: Symbol.LocalIndex, + }, }), +input_pending_index: u32, input_sections: std.ArrayList(InputSection), input_section_pending_index: u32, navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct { @@ -181,7 +187,10 @@ input_prog_node: std.Progress.Node, const Error = link.Error || error{MappedFileIo}; const Node = union(enum) { - file, + archive, + /// This includes the archive magic and long file member. + archive_header, + elf, ehdr, shdr, segment: u32, @@ -189,6 +198,8 @@ const Node = union(enum) { /// /// The section '.dynamic' may contain relocations via `elf.dynamic_first_symbol_reloc`. section: Section.Index, + /// Only valid for static libraries, represents one non-zcu archive member. + input_member: InputIndex, /// May contain relocations. input_section: InputSection.Index, /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for @@ -219,19 +230,23 @@ const Node = union(enum) { return elf.inputs.items[@backingInt(ii)].member; } + pub fn node(ii: InputIndex, elf: *const Elf) MappedFile.Node.Index { + return elf.inputs.items[@backingInt(ii)].extra.node; + } + pub fn fileSymbol(ii: InputIndex, elf: *const Elf) Symbol.LocalIndex { - return elf.inputs.items[@backingInt(ii)].file_symbol; + return elf.inputs.items[@backingInt(ii)].extra.file_symbol; } pub fn localSymbolRange(ii: InputIndex, elf: *Elf) [2]Symbol.LocalIndex { if (@backingInt(ii) + 1 < elf.inputs.items.len) { - const next_ii: InputIndex = @fromBackingInt(@intCast(@backingInt(ii) + 1)); + const next_ii: InputIndex = @fromBackingInt(@backingInt(ii) + 1); return .{ ii.fileSymbol(elf), next_ii.fileSymbol(elf) }; } else { const local_symbols_len = switch (elf.shdrPtr(.symtab)) { inline else => |shdr| elf.targetLoad(&shdr.info), }; - return .{ ii.fileSymbol(elf), @fromBackingInt(@intCast(local_symbols_len)) }; + return .{ ii.fileSymbol(elf), @fromBackingInt(local_symbols_len) }; } } }; @@ -315,15 +330,16 @@ const Node = union(enum) { }; pub const Known = struct { - comptime file: MappedFile.Node.Index = .root, - comptime ehdr: MappedFile.Node.Index = @fromBackingInt(@intCast(1)), - comptime shdr: MappedFile.Node.Index = @fromBackingInt(@intCast(2)), - comptime rodata: MappedFile.Node.Index = @fromBackingInt(@intCast(3)), - comptime phdr: MappedFile.Node.Index = @fromBackingInt(@intCast(4)), - comptime text: MappedFile.Node.Index = @fromBackingInt(@intCast(5)), - comptime data: MappedFile.Node.Index = @fromBackingInt(@intCast(6)), - comptime data_rel_ro: MappedFile.Node.Index = @fromBackingInt(@intCast(7)), - + archive: MappedFile.Node.Index, + archive_header: MappedFile.Node.Index, + elf: MappedFile.Node.Index, + ehdr: MappedFile.Node.Index, + shdr: MappedFile.Node.Index, + rodata: MappedFile.Node.Index, + phdr: MappedFile.Node.Index, + text: MappedFile.Node.Index, + data: MappedFile.Node.Index, + data_rel_ro: MappedFile.Node.Index, tls: MappedFile.Node.Index, }; @@ -333,11 +349,11 @@ const Node = union(enum) { /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`. fn toAtom(ni: MappedFile.Node.Index) link.File.AtomId { - return @fromBackingInt(@intCast(@backingInt(ni))); + return @fromBackingInt(@backingInt(ni)); } /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`. fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index { - return @fromBackingInt(@intCast(@backingInt(atom))); + return @fromBackingInt(@backingInt(atom)); } }; @@ -424,13 +440,13 @@ const Section = struct { fn unwrap(opt: RelaIndex.Optional) ?RelaIndex { return switch (opt) { .none => null, - _ => @fromBackingInt(@intCast(@backingInt(opt))), + _ => @fromBackingInt(@backingInt(opt)), }; } }; fn toOptional(i: RelaIndex) RelaIndex.Optional { - return @fromBackingInt(@intCast(@backingInt(i))); + return @fromBackingInt(@backingInt(i)); } }; @@ -465,8 +481,8 @@ const Section = struct { pub fn fromSection(sec: std.elf.Section) Index { return switch (sec) { - std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(@intCast(sec)), - std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(@intCast(reserve(sec))), + std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(sec), + std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)), }; } pub fn toSection(s: Index) ?std.elf.Section { @@ -485,7 +501,7 @@ const Section = struct { fn name(s: Index, elf: *Elf) String(.shstrtab) { return switch (elf.shdrPtr(s)) { - inline else => |shdr| @fromBackingInt(@intCast(elf.targetLoad(&shdr.name))), + inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)), }; } @@ -928,21 +944,7 @@ const GotReloc = struct { } } fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { - const node_vaddr: u64 = switch (elf.getNode(reloc.node)) { - .file => unreachable, - .ehdr => unreachable, - .shdr => unreachable, - .segment => unreachable, - .copied_global => unreachable, - .section => |shndx| shndx.vaddr(elf), - .input_section => |isi| isi.ptrConst(elf).vaddr, - inline .nav, - .uav, - .lazy_code, - .lazy_const_data, - => |i| Symbol.Id.local(i.symbol(elf)).value(elf), - }; - const dest_vaddr = node_vaddr + reloc.offset; + const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; const got_vaddr = elf.shndx.got.vaddr(elf); @@ -1131,12 +1133,12 @@ pub const MachineRelocType = union { pub fn wrap(int: u32, elf: *const Elf) MachineRelocType { return switch (elf.ehdrMachine()) { - .AARCH64 => .{ .AARCH64 = @fromBackingInt(@intCast(int)) }, - .LOONGARCH => .{ .LARCH = @fromBackingInt(@intCast(int)) }, - .PPC64 => .{ .PPC64 = @fromBackingInt(@intCast(int)) }, - .RISCV => .{ .RISCV = @fromBackingInt(@intCast(int)) }, - .SPARCV9 => .{ .SPARC = @fromBackingInt(@intCast(int)) }, - .X86_64 => .{ .X86_64 = @fromBackingInt(@intCast(int)) }, + .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) }, + .LOONGARCH => .{ .LARCH = @fromBackingInt(int) }, + .PPC64 => .{ .PPC64 = @fromBackingInt(int) }, + .RISCV => .{ .RISCV = @fromBackingInt(int) }, + .SPARCV9 => .{ .SPARC = @fromBackingInt(int) }, + .X86_64 => .{ .X86_64 = @fromBackingInt(int) }, }; } pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 { @@ -1646,21 +1648,7 @@ const SymbolReloc = struct { } } fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { - const node_vaddr: u64 = switch (elf.getNode(reloc.node)) { - .file => unreachable, - .ehdr => unreachable, - .shdr => unreachable, - .segment => unreachable, - .copied_global => unreachable, - .section => |shndx| shndx.vaddr(elf), - .input_section => |isi| isi.ptrConst(elf).vaddr, - inline .nav, - .uav, - .lazy_code, - .lazy_const_data, - => |i| Symbol.Id.local(i.symbol(elf)).value(elf), - }; - const dest_vaddr = node_vaddr + reloc.offset; + const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; const addend: u64 = @bitCast(reloc.addend); @@ -1875,7 +1863,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L // `shdr.info` stores the index of the first global symbol. We will replace it with our // new local symbol, and move the global symbol to a new index at the end of the symtab. - const target_index: Symbol.Index = @fromBackingInt(@intCast(elf.targetLoad(&shdr.info))); + const target_index: Symbol.Index = @fromBackingInt(elf.targetLoad(&shdr.info)); const old_size = elf.targetLoad(&shdr.size); const new_size = old_size + ent_size; @@ -1897,7 +1885,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L // ...then the `elf.symtab` metadata... new_index.ptr(elf).* = target_index.ptr(elf).*; // ...then update the `elf.globals` tracking. - const global_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&new_sym.name))); + const global_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&new_sym.name)); elf.globalByName(global_name).?.symtab_index = new_index; if (elf.ehdrType() == .REL and target_index.ptr(elf).first_target_reloc != .none) { @@ -1923,7 +1911,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); } - return @fromBackingInt(@intCast(@backingInt(target_index))); + return @fromBackingInt(@backingInt(target_index)); }, } } @@ -2371,7 +2359,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { inline else => |shdr, class| { // `shdr.info` stores the index of the first global symbol. We are going to swap the // demoted symbol with that first global symbol, then increment that start index. - const dest_index: Symbol.Index = @fromBackingInt(@intCast(elf.targetLoad(&shdr.info))); + const dest_index: Symbol.Index = @fromBackingInt(elf.targetLoad(&shdr.info)); const src_index = global_ptr.symtab_index; // This global should currently be in the "global symbols" part of the symtab, since our @@ -2387,10 +2375,10 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { const src_sym_ptr = @field(elf.symPtr(src_index), @tagName(class)); const dest_sym_ptr = @field(elf.symPtr(dest_index), @tagName(class)); - const this_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&src_sym_ptr.name))); + const this_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&src_sym_ptr.name)); assert(elf.globalByName(this_name).? == global_ptr); - const other_name: String(.strtab) = @fromBackingInt(@intCast(elf.targetLoad(&dest_sym_ptr.name))); + const other_name: String(.strtab) = @fromBackingInt(elf.targetLoad(&dest_sym_ptr.name)); const other_global_ptr = elf.globalByName(other_name).?; assert(other_global_ptr.symtab_index == dest_index); @@ -2426,7 +2414,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class)); const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class)); - const moved_name_dynstr: String(.dynstr) = @fromBackingInt(@intCast(elf.targetLoad(&src_dynsym_ptr.name))); + const moved_name_dynstr: String(.dynstr) = @fromBackingInt(elf.targetLoad(&src_dynsym_ptr.name)); const moved_name = elf.stringExisting(.strtab, moved_name_dynstr.slice(elf)); const moved_global_ptr = elf.globalByName(moved_name).?; @@ -2505,7 +2493,7 @@ const Symbol = struct { _, fn index(li: LocalIndex) Index { - return @fromBackingInt(@intCast(@backingInt(li))); + return @fromBackingInt(@backingInt(li)); } }; @@ -2527,16 +2515,16 @@ const Symbol = struct { global: String(.strtab), } { return switch (s.kind) { - .local => .{ .local = @fromBackingInt(@intCast(s.raw)) }, - .global => .{ .global = @fromBackingInt(@intCast(s.raw)) }, + .local => .{ .local = @fromBackingInt(s.raw) }, + .global => .{ .global = @fromBackingInt(s.raw) }, }; } fn toTypeErased(s: Symbol.Id) link.File.SymbolId { - return @fromBackingInt(@intCast(@as(u32, @bitCast(s)))); + return @bitCast(s); } fn fromTypeErased(s: link.File.SymbolId) Symbol.Id { - return @bitCast(@backingInt(s)); + return @bitCast(s); } fn index(s: Symbol.Id, elf: *const Elf) Symbol.Index { @@ -2648,24 +2636,10 @@ const Symbol = struct { .yes_textrel => elf.textrel_count += 1, .yes => {}, } - const node_vaddr: u64 = switch (elf.getNode(reloc.node)) { - .file => unreachable, - .ehdr => unreachable, - .shdr => unreachable, - .segment => unreachable, - .copied_global => unreachable, - .section => |shndx| shndx.vaddr(elf), - .input_section => |isi| isi.ptrConst(elf).vaddr, - inline .nav, - .uav, - .lazy_code, - .lazy_const_data, - => |i| Symbol.Id.local(i.symbol(elf)).value(elf), - }; // There is capacity for a relocation because we just deleted one earlier. reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ .type = .relative(elf), - .offset = node_vaddr + reloc.offset, + .offset = elf.getNodeVAddr(reloc.node) + reloc.offset, .raw_sym_index = 0, .addend = 0, }).toOptional(); @@ -2771,11 +2745,14 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { - .file, + .archive, + .archive_header, + .elf, .ehdr, .shdr, .segment, .section, + .input_member, .input_section, .copied_global, => unreachable, @@ -3001,12 +2978,12 @@ fn String(section: StringSection) type { } fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) { const st: *StringTable = &@field(elf, @tagName(section)); - return @fromBackingInt(@intCast(try st.get(elf, section.shndx(elf), key))); + return @fromBackingInt(try st.get(elf, section.shndx(elf), key)); } /// Like `string`, but asserts that the string is already in `section`. fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) String(section) { const st: *StringTable = &@field(elf, @tagName(section)); - return @fromBackingInt(@intCast(st.getExisting(elf, section.shndx(elf), key))); + return @fromBackingInt(st.getExisting(elf, section.shndx(elf), key)); } const StringTable = struct { @@ -3172,6 +3149,16 @@ fn create( .options = options, .mf = try .init(file, comp.gpa, io), .ni = .{ + .archive = .root, + .archive_header = .none, + .elf = .root, + .ehdr = .none, + .shdr = .none, + .rodata = .none, + .phdr = .none, + .text = .none, + .data = .none, + .data_rel_ro = .none, .tls = .none, }, .nodes = .empty, @@ -3218,6 +3205,7 @@ fn create( .dynamic_first_symbol_reloc = .none, .needed = .empty, .inputs = .empty, + .input_pending_index = 0, .input_sections = .empty, .input_section_pending_index = 0, .navs = .empty, @@ -3293,6 +3281,7 @@ fn initHeaders( const comp = elf.base.comp; const gpa = comp.gpa; + const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; const have_dynamic_section = switch (@"type") { .REL => false, .EXEC => comp.config.link_mode == .dynamic, @@ -3389,7 +3378,8 @@ fn initHeaders( }, phnum }; }; - const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes + const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header + 3 + // `.file`, `.ehdr`, and `.shdr` nodes (shnum - 1) + // -1 because the null shdr does not have a `.section` node (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node @@ -3398,17 +3388,49 @@ fn initHeaders( try elf.section_by_name.ensureUnusedCapacity(gpa, shnum); try elf.phdrs.resize(gpa, phnum); try elf.symtab.ensureTotalCapacity(gpa, 1); - elf.nodes.appendAssumeCapacity(.file); + + if (is_archive) { + elf.nodes.appendAssumeCapacity(.archive); + elf.ni.archive_header = try elf.mf.addOnlyChildNode(gpa, elf.ni.archive, .{ + .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr) * 2, + .alignment = .@"2", + .fixed = true, + .next_moved = true, + .bubbles_moved = false, + .enable_next_moved = true, + }); + const archive_header_slice = elf.ni.archive_header.slice(&elf.mf); + @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG); + const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]); + strtab_ar_hdr.* = .{ + .ar_name = std.elf.STRNAME.*, + .ar_date = @splat(' '), + .ar_uid = @splat(' '), + .ar_gid = @splat(' '), + .ar_mode = @splat(' '), + .ar_size = @splat(' '), + .ar_fmag = std.elf.ARFMAG.*, + }; + + elf.nodes.appendAssumeCapacity(.archive_header); + elf.ni.elf = try elf.mf.addLastChildNode(gpa, elf.ni.archive, .{ + .alignment = elf.mf.flags.block_size.max(.@"2"), + .next_moved = true, + .bubbles_moved = false, + .enable_next_moved = true, + }); + } + elf.nodes.appendAssumeCapacity(.elf); const entsize: struct { ph: u32, sh: u32 } = switch (class) { .NONE, _ => unreachable, inline else => |ct_class| entsize: { const ElfN = ct_class.ElfN(); - assert(elf.ni.ehdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.file, .{ + elf.ni.ehdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ .size = @sizeOf(ElfN.Ehdr), .alignment = addr_align, .fixed = true, - })); + }); elf.nodes.appendAssumeCapacity(.ehdr); const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); @@ -3461,12 +3483,12 @@ fn initHeaders( }, }; - assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ + elf.ni.shdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ .size = 1 * entsize.sh, // as above, only the null shdr initially .alignment = elf.mf.flags.block_size, .moved = true, .resized = true, - })); + }); elf.nodes.appendAssumeCapacity(.shdr); const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) { @@ -3491,45 +3513,45 @@ fn initHeaders( }); var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: { - assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ + elf.ni.rodata = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ .alignment = elf.mf.flags.block_size, .moved = true, .bubbles_moved = false, - })); + }); elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata }); elf.phdrs.items[phndx.rodata] = elf.ni.rodata; - assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{ + elf.ni.phdr = try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{ .size = @as(u64, phnum) * entsize.ph, .alignment = addr_align, .moved = true, .resized = true, .bubbles_moved = false, - })); + }); elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr }); elf.phdrs.items[phndx.phdr] = elf.ni.phdr; - assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ + elf.ni.text = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ .alignment = elf.mf.flags.block_size, .moved = true, .bubbles_moved = false, - })); + }); elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text }); elf.phdrs.items[phndx.text] = elf.ni.text; - assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ + elf.ni.data = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ .alignment = elf.mf.flags.block_size, .moved = true, .bubbles_moved = false, - })); + }); elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); elf.phdrs.items[phndx.data] = elf.ni.data; - assert(elf.ni.data_rel_ro == try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ + elf.ni.data_rel_ro = try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ .alignment = elf.mf.flags.block_size, .moved = true, .bubbles_moved = false, - })); + }); elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro }); elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro; @@ -3706,7 +3728,7 @@ fn initHeaders( .node = .none, .first_target_reloc = .none, }; - assert(.symtab == try elf.addSection(elf.ni.file, .{ + assert(.symtab == try elf.addSection(elf.ni.elf, .{ .type = .SYMTAB, .size = @sizeOf(ElfN.Sym) * 1, .addralign = addr_align, @@ -3729,7 +3751,7 @@ fn initHeaders( ehdr.shstrndx = ehdr.shnum; }, } - assert(.shstrtab == try elf.addSection(elf.ni.file, .{ + assert(.shstrtab == try elf.addSection(elf.ni.elf, .{ .type = .STRTAB, .size = 1, .entsize = 1, @@ -3740,7 +3762,7 @@ fn initHeaders( try Section.Index.symtab.rename(elf, ".symtab"); try Section.Index.shstrtab.rename(elf, ".shstrtab"); - assert(.strtab == try elf.addSection(elf.ni.file, .{ + assert(.strtab == try elf.addSection(elf.ni.elf, .{ .name = ".strtab", .type = .STRTAB, .size = 1, @@ -4210,6 +4232,8 @@ fn initHeaders( break :str try elf.string(.dynstr, slice); }, }; + + try elf.ensureElfNodeSize(); } pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { @@ -4221,10 +4245,8 @@ pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { break :count count; }); elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len); - elf.input_prog_node = prog_node.start( - "Inputs", - elf.input_sections.items.len - elf.input_section_pending_index, - ); + elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) + + (elf.input_sections.items.len - elf.input_section_pending_index)); } pub fn endProgress(elf: *Elf) void { @@ -4244,13 +4266,15 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { /// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data. fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { return switch (elf.getNode(ni)) { - .file => unreachable, - .ehdr => unreachable, - .shdr => unreachable, - .segment => unreachable, - + .archive, + .archive_header, + .elf, + .ehdr, + .shdr, + .segment, + .input_member, + => unreachable, .section => |shndx| shndx, - .input_section, .copied_global, .nav, @@ -4260,21 +4284,44 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { => elf.getNode(ni.parent(&elf.mf)).section, }; } +fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { + return switch (elf.getNode(ni)) { + .archive, + .archive_header, + .elf, + .ehdr, + .shdr, + .segment, + .input_member, + .copied_global, + => unreachable, + .section => |shndx| shndx.vaddr(elf), + .input_section => |isi| isi.ptrConst(elf).vaddr, + inline .nav, + .uav, + .lazy_code, + .lazy_const_data, + => |i| Symbol.Id.local(i.symbol(elf)).value(elf), + }; +} fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf))) { - .file => return 0, + .archive, .archive_header => unreachable, + .elf => return 0, .ehdr, .shdr => unreachable, .segment => |phndx| switch (elf.phdrSlice()) { inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), }, .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), - .input_section => unreachable, - .copied_global => unreachable, + .input_member, .input_section, .copied_global => unreachable, inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf), }; const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); return parent_vaddr + offset; } +fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { + return ni.fileLocation(&elf.mf, false).offset - elf.ni.elf.fileLocation(&elf.mf, false).offset; +} /// Deletes any existing relocations in the given node, and marks the start of the node's contiguous /// sequence of relocations, so that the caller may append the node's updated relocations. @@ -4283,12 +4330,16 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { /// the special-case sections '.plt' and '.dynamic'. fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { - .file => unreachable, // cannot contain relocs - .ehdr => unreachable, // cannot contain relocs - .shdr => unreachable, // cannot contain relocs - .segment => unreachable, // cannot contain relocs + .archive, + .archive_header, + .elf, + .ehdr, + .shdr, + .segment, + .input_member, + .copied_global, + => unreachable, // cannot contain relocs .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported) - .copied_global => unreachable, // cannot contain relocs .input_section => |isi| .{ &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, &elf.input_sections.items[@backingInt(isi)].first_got_reloc, @@ -4359,7 +4410,7 @@ fn flushMovedNodeRelocs( } fn identClass(elf: *const Elf) std.elf.CLASS { - return @fromBackingInt(@intCast(elf.mf.memory_map.memory[std.elf.EI.CLASS])); + return @fromBackingInt(elf.ni.elf.sliceConst(&elf.mf)[std.elf.EI.CLASS]); } /// Like `std.elf.ET`, but only includes the ELF machine architectures we support, so that we can @@ -4415,7 +4466,7 @@ fn targetPtrSize(elf: *const Elf) u8 { return elf.identClass().size(); } fn targetEndian(elf: *const Elf) std.lang.Endian { - const ident_data: std.elf.DATA = @fromBackingInt(@intCast(elf.mf.memory_map.memory[std.elf.EI.DATA])); + const ident_data: std.elf.DATA = @fromBackingInt(elf.ni.elf.sliceConst(&elf.mf)[std.elf.EI.DATA]); return ident_data.endian(); } fn targetTlsVariant(elf: *const Elf) union(enum) { @@ -4487,7 +4538,7 @@ fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.chi return switch (@typeInfo(Child)) { else => @compileError(@typeName(Child)), .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()), - .@"enum" => |@"enum"| @fromBackingInt(@intCast(elf.targetLoad(@as(*align(alignment) const @"enum".tag_type, @ptrCast(ptr))))), + .@"enum" => |@"enum"| @fromBackingInt(elf.targetLoad(@as(*align(alignment) const @"enum".tag_type, @ptrCast(ptr)))), .@"struct" => |@"struct"| @bitCast( elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))), ), @@ -4563,6 +4614,16 @@ fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr { } } +fn arHdrPtr(elf: *Elf, ni: MappedFile.Node.Index) *align(2) std.elf.ar_hdr { + assert(elf.ni.elf != MappedFile.Node.Index.root); + const file_offset = ni.fileLocation(&elf.mf, false).offset; + return @ptrCast(@alignCast(elf.mf.memory_map.memory[@intCast(switch (elf.getNode(ni)) { + else => unreachable, + .archive_header => file_offset + std.elf.ARMAG.len, + .elf, .input_member => file_offset - @sizeOf(std.elf.ar_hdr), + })..][0..@sizeOf(std.elf.ar_hdr)])); +} + const SymPtr = union(std.elf.CLASS) { NONE: noreturn, @"32": *std.elf.Elf32.Sym, @@ -4657,7 +4718,7 @@ fn mapInputSection(elf: *Elf, opts: struct { } errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab); const parent_node: MappedFile.Node.Index = parent: { - if (!opts.flags.ALLOC) break :parent elf.ni.file; + if (!opts.flags.ALLOC) break :parent elf.ni.elf; if (opts.flags.EXECINSTR) break :parent elf.ni.text; if (opts.flags.TLS) break :parent elf.ni.tls; if (opts.flags.WRITE) break :parent elf.ni.data; @@ -4878,7 +4939,7 @@ const LoadParseInputError = Error || Io.File.SeekError || Io.Reader.Error; /// indicates to the frontend that the input could be a GNU ld script instead. pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void { const diags = &elf.base.comp.link_diags; - return elf.loadInputInner(input) catch |err| switch (err) { + elf.loadInputInner(input) catch |err| switch (err) { else => |e| return e, error.MappedFileIo => return diags.fail( "failed to write output file: {t}", @@ -4986,6 +5047,9 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load const r = &fr.interface; log.debug("loadArchive({f})", .{path.fmtEscapeString()}); + + if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact + { const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) { error.ReadFailed => |e| return e, @@ -5071,21 +5135,40 @@ fn loadObject( .{}, ), }; + + const input = try elf.inputs.addOne(gpa); + input.* = .{ + .path = path, + .member = if (member) |m| try gpa.dupe(u8, m) else null, + .extra = undefined, + }; + if (elf.ni.elf != MappedFile.Node.Index.root) { + try elf.nodes.ensureUnusedCapacity(gpa, 1); + input.extra = .{ .node = try elf.mf.addLastChildNode(gpa, .root, .{ + .size = fl.size + @sizeOf(std.elf.ar_hdr), + .alignment = .@"2", + .next_moved = true, + .bubbles_moved = false, + .enable_next_moved = true, + }) }; + elf.nodes.appendAssumeCapacity(.{ .input_member = input_index }); + elf.input_prog_node.increaseEstimatedTotalItems(1); + + // Since we are not emitting the archive symbol table (yet?) we do not need to parse + // the symbols in this input. + return; + } + + elf.input_pending_index += 1; try elf.ensureUnusedSymbolCapacity(1, .all_local); - try elf.inputs.ensureUnusedCapacity(gpa, 1); - const file_symbol = elf.addLocalSymbolAssumeCapacity(.{ + input.extra = .{ .file_symbol = elf.addLocalSymbolAssumeCapacity(.{ .node = .none, .name = try elf.string(.strtab, std.fs.path.stem(member orelse path.sub_path)), .value = 0, .size = 0, .type = .FILE, .shndx = .ABS, - }); - elf.inputs.addOneAssumeCapacity().* = .{ - .path = path, - .member = if (member) |m| try gpa.dupe(u8, m) else null, - .file_symbol = file_symbol, - }; + }) }; const target_endian = elf.targetEndian(); switch (elf.identClass()) { .NONE, _ => unreachable, @@ -5479,6 +5562,9 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars log.debug("loadDso({f})", .{path.fmtEscapeString()}); try elf.checkInputIdent(path, r); + + if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact + const target_endian = elf.targetEndian(); switch (elf.identClass()) { .NONE, _ => unreachable, @@ -5709,7 +5795,8 @@ fn checkInputIdent( } const ident = try r.peekStructPointer(std.elf.Ident); - const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]); + const target: *const std.elf.Ident = + @ptrCast(elf.ni.elf.sliceConst(&elf.mf)[0..@sizeOf(std.elf.Ident)]); if (ident.class != target.class) return diags.failParse( path, @@ -5825,13 +5912,11 @@ fn prelinkInner(elf: *Elf) Error!void { const comp = elf.base.comp; const gpa = comp.gpa; - if (comp.zcu != null and !comp.config.use_llvm) { - // We're use self-hosted codegen---add an input representing the Zig "object". + if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == MappedFile.Node.Index.root) { + // We're using self-hosted codegen---add an input representing the Zig "object". try elf.ensureUnusedSymbolCapacity(1, .all_local); try elf.inputs.ensureUnusedCapacity(gpa, 1); - const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{ - std.fs.path.stem(elf.base.emit.sub_path), - }); + const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{comp.root_name}); defer gpa.free(zcu_name); const zcu_file_symbol = elf.addLocalSymbolAssumeCapacity(.{ .node = .none, @@ -5844,9 +5929,12 @@ fn prelinkInner(elf: *Elf) Error!void { elf.inputs.addOneAssumeCapacity().* = .{ .path = elf.base.emit, .member = null, - .file_symbol = zcu_file_symbol, + .extra = .{ .file_symbol = zcu_file_symbol }, }; + elf.input_pending_index += 1; } + + try elf.ensureElfNodeSize(); } fn prepareDynamic(elf: *Elf) Error!void { @@ -6036,12 +6124,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { }, }; assert(shndx < @backingInt(Section.Index.LORESERVE)); - break :shndx .{ @fromBackingInt(@intCast(shndx)), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) }; + break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) }; }, }; try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size); const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrType()) { - .REL => elf.ni.file, + .REL => elf.ni.elf, .EXEC, .DYN => segment_ni, }, .{ .size = opts.size, @@ -6064,7 +6152,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { else => .{ .shndx = .UNDEF }, } }); elf.nodes.appendAssumeCapacity(.{ .section = shndx }); - const offset = ni.fileLocation(&elf.mf, false).offset; switch (elf.shdrPtr(shndx)) { inline else => |shdr, class| { shdr.* = .{ @@ -6072,7 +6159,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { .type = opts.type, .flags = .{ .shf = opts.flags }, .addr = @intCast(addr), - .offset = @intCast(offset), + .offset = @intCast(elf.getNodeElfOffset(ni)), .size = @intCast(opts.size), .link = opts.link, .info = opts.info, @@ -6506,20 +6593,7 @@ fn addSymbolRelocAssumeCapacity( // If we emit a runtime relocation entry, its `offset` is a virtual address, so we need to // determine the vaddr of `node`. - const node_vaddr: u64 = switch (elf.getNode(node)) { - .file => unreachable, - .ehdr => unreachable, - .shdr => unreachable, - .segment => unreachable, - .copied_global => unreachable, - .section => |shndx| shndx.vaddr(elf), - .input_section => |isi| isi.ptrConst(elf).vaddr, - inline .nav, - .uav, - .lazy_code, - .lazy_const_data, - => |i| Symbol.Id.local(i.symbol(elf)).value(elf), - }; + const node_vaddr = elf.getNodeVAddr(node); // If this is `true`, we will try to create a copy relocation for the target symbol if it is // not locally defined. If the relocation value is always computed from the target symbol's @@ -6658,20 +6732,23 @@ fn addGotRelocAssumeCapacity( ) void { assert(elf.ehdrType() != .REL); switch (elf.getNode(node)) { + .archive, + .archive_header, + .elf, + .ehdr, + .shdr, + .segment, + .input_member, + .copied_global, + => unreachable, // cannot contain relocs, + .section, + .uav, + => unreachable, // cannot contain GOT relocs .input_section, .nav, .lazy_code, .lazy_const_data, => {}, - - .section => unreachable, // cannot contain GOT relocs - .uav => unreachable, // cannot contain GOT relocs - - .file => unreachable, // cannot contain relocs - .ehdr => unreachable, // cannot contain relocs - .shdr => unreachable, // cannot contain relocs - .segment => unreachable, // cannot contain relocs - .copied_global => unreachable, // cannot contain relocs } const gop = elf.got.getOrPutAssumeCapacity(target); @@ -7055,6 +7132,17 @@ pub fn flush( tid: Zcu.PerThread.Id, prog_node: std.Progress.Node, ) link.Error!void { + elf.flushInner(arena, tid, prog_node) catch |err| switch (err) { + error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), + else => |e| return e, + }; +} +fn flushInner( + elf: *Elf, + arena: std.mem.Allocator, + tid: Zcu.PerThread.Id, + prog_node: std.Progress.Node, +) Error!void { const comp = elf.base.comp; const diags = &comp.link_diags; _ = arena; @@ -7072,11 +7160,9 @@ pub fn flush( if (any_undef) return error.AlreadyReported; } - elf.prepareDynamic() catch |err| switch (err) { - error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), - else => |e| return e, - }; + try elf.prepareDynamic(); + try elf.ensureElfNodeSize(); while (try elf.idle(tid)) {} // We've done the final `idle` loop, so everything is at its final place in the file. We have a @@ -7101,10 +7187,7 @@ pub fn flush( .enabled => "_start", .named => |named| named, }; - const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) { - error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), - else => |e| return e, - }; + const sym_name_strtab = try elf.string(.strtab, sym_name_slice); if (elf.globalByName(sym_name_strtab) == null) break :entry 0; break :entry Symbol.Id.global(sym_name_strtab).value(elf); }; @@ -7112,10 +7195,11 @@ pub fn flush( inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)), } - elf.mf.flush() catch |err| switch (err) { - error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), - else => |e| return e, - }; + try elf.mf.flush(); + + if (elf.options.enable_link_snapshots) + elf.dumpStderr(tid) catch |err| + return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); } pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { @@ -7128,8 +7212,19 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { } task: { + if (elf.input_pending_index < elf.inputs.items.len) { + const ii: Node.InputIndex = @fromBackingInt(elf.input_pending_index); + elf.input_pending_index += 1; + const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf))); + defer sub_prog_node.end(); + elf.flushInput(ii) catch |err| switch (err) { + error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), + else => |e| return e, + }; + break :task; + } if (elf.input_section_pending_index < elf.input_sections.items.len) { - const isi: InputSection.Index = @fromBackingInt(@intCast(elf.input_section_pending_index)); + const isi: InputSection.Index = @fromBackingInt(elf.input_section_pending_index); elf.input_section_pending_index += 1; const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); defer sub_prog_node.end(); @@ -7217,11 +7312,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { while (elf.mf.updates.pop()) |ni| { const clean_moved = ni.cleanMoved(&elf.mf); const clean_resized = ni.cleanResized(&elf.mf); - if (clean_moved or clean_resized) { + const clean_next_moved = ni.cleanNextMoved(&elf.mf); + if (clean_moved or clean_resized or clean_next_moved) { const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); defer sub_prog_node.end(); if (clean_moved) try elf.flushMoved(ni); if (clean_resized) try elf.flushResized(ni); + if (clean_next_moved) try elf.flushNextMoved(ni); break :task; } else elf.mf.update_prog_node.completeOne(); } @@ -7242,6 +7339,10 @@ fn idleProgNode( return prog_node.start(name: switch (node) { else => |tag| @tagName(tag), .section => |shndx| shndx.name(elf).slice(elf), + .input_member => |ii| std.fmt.bufPrint(&name, "{f}{f}", .{ + ii.path(elf).fmtEscapeString(), + fmtMemberString(ii.member(elf)), + }) catch &name, .input_section => |isi| { const ii = isi.input(elf); break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ @@ -7294,6 +7395,8 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void { }; break; } + + try elf.ensureElfNodeSize(); } fn genUav( @@ -7362,6 +7465,36 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { } } +fn flushInput(elf: *Elf, ii: Node.InputIndex) Error!void { + const comp = elf.base.comp; + const io = comp.io; + const gpa = comp.gpa; + const diags = &comp.link_diags; + const path = ii.path(elf); + const file = path.root_dir.handle.openFile(io, path.sub_path, .{}) catch |err| switch (err) { + error.Canceled => |e| return e, + else => |e| return diags.fail("failed to open input file \"{f}\": {t}", .{ path.fmtEscapeString(), e }), + }; + defer file.close(io); + var fr = file.reader(io, &.{}); + var nw: MappedFile.Node.Writer = undefined; + ii.node(elf).writer(&elf.mf, gpa, &nw); + defer nw.deinit(); + const size = nw.interface.buffer.len - @sizeOf(std.elf.ar_hdr); + const n_bytes = nw.interface.sendFileAll(&fr, .limited(size)) catch |err| switch (err) { + error.ReadFailed => return diags.fail("failed to read input \"{f}{f}\": {t}", .{ + path.fmtEscapeString(), + fmtMemberString(ii.member(elf)), + fr.err orelse (fr.seek_err orelse fr.size_err.?), + }), + error.WriteFailed => return nw.err.?, + }; + if (n_bytes + 1 < size) return diags.fail("failed to read input \"{f}{f}\": unexpected eof", .{ + path.fmtEscapeString(), + fmtMemberString(ii.member(elf)), + }); +} + fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { const file_loc = isi.fileLocation(elf); if (file_loc.size == 0) return; @@ -7408,33 +7541,29 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { assert(isi.node(elf).hasMoved(&elf.mf)); } -fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void { +fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { + const elf_offset = elf.getNodeElfOffset(ni); switch (elf.getNode(ni)) { else => unreachable, - .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0), + .ehdr => assert(elf_offset == 0), .shdr => switch (elf.ehdrPtr()) { - inline else => |ehdr| elf.targetStore( - &ehdr.shoff, - @intCast(ni.fileLocation(&elf.mf, false).offset), - ), + inline else => |ehdr| elf.targetStore(&ehdr.shoff, @intCast(elf_offset)), }, .segment => |phndx| { switch (elf.phdrSlice()) { inline else => |phdr, class| { const ph = &phdr[phndx]; - elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset)); + elf.targetStore(&ph.offset, @intCast(elf_offset)); if (elf.targetLoad(&ph.type) == .PHDR) { @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset; } }, } var child_it = ni.children(&elf.mf); - while (child_it.next()) |child_ni| elf.flushFileOffset(child_ni); + while (child_it.next()) |child_ni| elf.flushElfOffset(child_ni); }, .section => |shndx| switch (elf.shdrPtr(shndx)) { - inline else => |shdr| elf.targetStore(&shdr.offset, @intCast( - ni.fileLocation(&elf.mf, false).offset, - )), + inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), }, } } @@ -7447,10 +7576,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void defer elf.mf.nodes_lock.unlock(); switch (elf.getNode(ni)) { - .file => unreachable, - .ehdr, .shdr => elf.flushFileOffset(ni), + .archive, .archive_header => unreachable, + .elf => {}, + .ehdr, .shdr => elf.flushElfOffset(ni), .segment => |phndx| { - elf.flushFileOffset(ni); + elf.flushElfOffset(ni); switch (elf.phdrSlice()) { inline else => |phdr| { const ph = &phdr[phndx]; @@ -7471,7 +7601,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void } }, .section => |shndx| { - elf.flushFileOffset(ni); + elf.flushElfOffset(ni); const addr = elf.computeNodeVAddr(ni); const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { inline else => |shdr| .{ @@ -7522,6 +7652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void elf.flushMovedNodeRelocs(ni, addr, elf.dynamic_first_symbol_reloc, .none); } }, + .input_member => {}, .input_section => |isi| { const old_section_addr = isi.ptr(elf).vaddr; const new_section_addr = elf.computeNodeVAddr(ni); @@ -7530,7 +7661,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void // Update local symbols const ii = isi.input(elf); var lsi, const end_lsi = ii.localSymbolRange(elf); - while (lsi != end_lsi) : (lsi = @fromBackingInt(@intCast(@backingInt(lsi) + 1))) { + while (lsi != end_lsi) : (lsi = @fromBackingInt(@backingInt(lsi) + 1)) { if (lsi.index().ptr(elf).node != ni) continue; const visibility: std.elf.STV = switch (elf.symPtr(lsi.index())) { inline else => |sym| elf.targetLoad(&sym.other).visibility, @@ -7617,7 +7748,17 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo _, const size = ni.location(&elf.mf).resolve(&elf.mf); switch (elf.getNode(ni)) { - .file => {}, + .archive => { + var child_it = ni.reverseChildren(&elf.mf); + if (child_it.next()) |last_ni| { + if (child_it.next()) |prev_ni| if (prev_ni.hasNextMoved(&elf.mf)) return; + const offset, _ = last_ni.location(&elf.mf).resolve(&elf.mf); + _ = std.mem.print(&elf.arHdrPtr(last_ni).ar_size, "{d:<10}", .{ + size - offset, + }) catch @panic("archive member too large"); + } + }, + .archive_header, .elf => {}, .ehdr => unreachable, .shdr => {}, .segment => |phndx| switch (elf.phdrSlice()) { @@ -7717,9 +7858,88 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo } }, }, - .copied_global, .input_section, .nav, .uav, .lazy_code, .lazy_const_data => {}, + .input_member, .input_section, .copied_global, .nav, .uav, .lazy_code, .lazy_const_data => {}, } } + +fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { + const trace = tracy.trace(@src()); + defer trace.end(); + + elf.mf.nodes_lock.lock(); + defer elf.mf.nodes_lock.unlock(); + + switch (elf.getNode(ni)) { + .archive, + .ehdr, + .shdr, + .segment, + .section, + .input_section, + .copied_global, + .nav, + .uav, + .lazy_code, + .lazy_const_data, + => unreachable, + .archive_header, .elf, .input_member => |_, tag| { + const member_offset, const update_size = member_offset: { + const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); + break :member_offset switch (tag) { + else => unreachable, + .archive_header => .{ offset + std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr), true }, + .elf, .input_member => .{ offset, switch (ni.prev(&elf.mf)) { + .none => unreachable, + else => |prev_ni| !prev_ni.hasNextMoved(&elf.mf), + } }, + }; + }; + const member_size = member_end: switch (ni.next(&elf.mf)) { + else => |next_ni| { + const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf); + const next_member_size = next_member_end: switch (next_ni.next(&elf.mf)) { + else => |next_next_ni| { + const next_next_offset, _ = next_next_ni.location(&elf.mf).resolve(&elf.mf); + break :next_member_end next_next_offset - @sizeOf(std.elf.ar_hdr); + }, + .none => { + _, const parent_size = + ni.parent(&elf.mf).location(&elf.mf).resolve(&elf.mf); + break :next_member_end parent_size; + }, + } - next_offset; + const ar_hdr = elf.arHdrPtr(next_ni); + var name_buf: [16]u8 = undefined; + _ = std.mem.print(&ar_hdr.ar_name, "{s:<16}", .{ + switch (elf.getNode(next_ni)) { + else => unreachable, + .elf => std.mem.print(&name_buf, "{s}_zcu.o/", .{elf.base.comp.root_name}), + .input_member => |ii| std.mem.print(&name_buf, "{s}/", .{ + std.fs.path.basename(ii.path(elf).sub_path), + }), + } catch @panic("TODO: long archive member names"), + }) catch @panic("TODO: long archive member names"); + ar_hdr.ar_date = "0 ".*; + ar_hdr.ar_uid = "0 ".*; + ar_hdr.ar_gid = "0 ".*; + ar_hdr.ar_mode = "644 ".*; + _ = std.mem.print(&ar_hdr.ar_size, "{d:<10}", .{next_member_size}) catch + @panic("archive member too large"); + ar_hdr.ar_fmag = std.elf.ARFMAG.*; + break :member_end next_offset - @sizeOf(std.elf.ar_hdr); + }, + .none => { + _, const parent_size = ni.parent(&elf.mf).location(&elf.mf).resolve(&elf.mf); + break :member_end parent_size; + }, + } - member_offset; + if (update_size) _ = std.mem.print(&elf.arHdrPtr(ni).ar_size, "{d:<10}", .{ + member_size, + }) catch @panic("archive member too large"); + }, + } +} + fn updateDynamicEntry(elf: *Elf, key: u32, new_val: u64) void { switch (elf.shdrPtr(elf.shndx.dynamic)) { inline else => |shdr, class| { @@ -7760,7 +7980,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void }; // Now that we know the index, we can set the relocation's offset. - elf.shndx.rela_plt.relaSetOffset(elf, @fromBackingInt(@intCast(plt_index)), got_plt_section.vaddr(elf) + got_plt_offset); + elf.shndx.rela_plt.relaSetOffset(elf, @fromBackingInt(plt_index), got_plt_section.vaddr(elf) + got_plt_offset); if (plt_index < elf.plt.count()) { // We reused a free entry, so we're already done! @@ -8100,7 +8320,10 @@ fn updateExportsInner( }, .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT }, }; + + try elf.ensureElfNodeSize(); while (try elf.idle(pt.tid)) {} + const value: u64 = Symbol.Id.local(exported_lsi).value(elf); const size: u64, const shndx: Section.Index = switch (elf.symPtr(exported_lsi.index())) { inline else => |exported_sym| .{ @@ -8154,6 +8377,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm _ = name; } +fn dumpStderr(elf: *Elf, tid: Zcu.PerThread.Id) !void { + const comp = elf.base.comp; + const io = comp.io; + var buffer: [512]u8 = undefined; + const stderr = try io.lockStderr(&buffer, null); + defer io.unlockStderr(); + const w = &stderr.file_writer.interface; + _ = try elf.dump(w, tid); +} + pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { if (elf.options.enable_link_snapshots) { try elf.printNode(tid, w, .root, 0); @@ -8231,13 +8464,14 @@ pub fn printNode( { const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; const off, const size = mf_node.location().resolve(&elf.mf); - try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{ + try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}{s}\n", .{ @backingInt(ni), off, size, mf_node.flags.alignment.toByteUnits(), if (mf_node.flags.fixed) " fixed" else "", if (mf_node.flags.moved) " moved" else "", + if (mf_node.flags.next_moved) " next_moved" else "", if (mf_node.flags.resized) " resized" else "", if (mf_node.flags.has_content) " has_content" else "", }); @@ -8273,11 +8507,19 @@ pub fn printNode( } } -fn ensureNodeSize( - elf: *Elf, - node: MappedFile.Node.Index, - need_size: u64, -) Error!void { +/// Must be called deterministically after any call to `MappedFile.Node.Index.resize` +/// (of `elf.ni.elf` or one of its children) before any possible calls to `idle`. +fn ensureElfNodeSize(elf: *Elf) MappedFile.Error!void { + if (elf.ni.elf == MappedFile.Node.Index.root) return; + var child_it = elf.ni.elf.reverseChildren(&elf.mf); + const last_end = if (child_it.next()) |last_ni| last_end: { + const last_offset, const last_size = last_ni.location(&elf.mf).resolve(&elf.mf); + break :last_end last_offset + last_size; + } else 0; + try elf.ensureNodeSize(elf.ni.elf, last_end + @sizeOf(std.elf.ar_hdr)); +} + +fn ensureNodeSize(elf: *Elf, node: MappedFile.Node.Index, need_size: u64) MappedFile.Error!void { _, const node_size = node.location(&elf.mf).resolve(&elf.mf); if (need_size <= node_size) return; const gpa = elf.base.comp.gpa; diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig index 6fd6e1ab4a27da8b582f8d5daa1ca122aeb546c9..fa8fe9e3936b87d4773d3e3b2abebe0b14ef017f 100644 --- a/src/link/MappedFile.zig +++ b/src/link/MappedFile.zig @@ -23,6 +23,7 @@ nodes: std.ArrayList(Node), free_ni: Node.Index, large: std.ArrayList(u64), updates: std.ArrayList(Node.Index), +/// This progress node's estimated total items is increased once for each node appended to `updates`. update_prog_node: std.Progress.Node, writers: std.SinglyLinkedList, io_err: ?IoError, @@ -61,7 +62,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{ MappedFileIo, }; -pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile { +pub fn init(file: Io.File, gpa: Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile { var mf: MappedFile = .{ .io = io, .flags = undefined, @@ -105,7 +106,7 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I return mf; } -pub fn deinit(mf: *MappedFile, gpa: std.mem.Allocator) void { +pub fn deinit(mf: *MappedFile, gpa: Allocator) void { mf.unmap(); mf.nodes.deinit(gpa); mf.large.deinit(gpa); @@ -133,11 +134,15 @@ pub const Node = extern struct { moved: bool, /// Whether this node has been resized. resized: bool, + /// Whether the next sibling has moved or is a different node. + next_moved: bool, /// Whether this node might contain non-zero bytes. has_content: bool, - /// Whether a moved event on this node bubbles down to children. + /// Whether `moved` events on this node bubble down to children. bubbles_moved: bool, - unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 6) = 0, + /// Whether `next_moved` events are reported in `updates`. + enable_next_moved: bool, + unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 8) = 0, }; pub const Location = union(enum(u1)) { @@ -191,6 +196,22 @@ pub const Node = extern struct { pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index { return ni.get(mf).next; } + fn setNext( + prev_ni: Node.Index, + gpa: Allocator, + next_ni: Node.Index, + mf: *MappedFile, + ) Allocator.Error!void { + assert(prev_ni != .none); + const prev_next = &prev_ni.get(mf).next; + if (prev_next.* == next_ni) return; + prev_next.* = next_ni; + try prev_ni.nextMoved(gpa, mf); + } + + pub fn prev(ni: Node.Index, mf: *const MappedFile) Node.Index { + return ni.get(mf).prev; + } pub fn ChildIterator(comptime direction: enum { prev, next }) type { return struct { @@ -211,7 +232,7 @@ pub const Node = extern struct { return .{ .mf = mf, .ni = ni.get(mf).last }; } - pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void { + pub fn childrenMoved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { var child_ni = ni.get(mf).last; while (child_ni != .none) { try child_ni.moved(gpa, mf); @@ -229,11 +250,11 @@ pub const Node = extern struct { } return false; } - pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void { - try mf.updates.ensureUnusedCapacity(gpa, 1); + pub fn moved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { + try mf.updates.ensureUnusedCapacity(gpa, 2); ni.movedAssumeCapacity(mf); } - pub fn cleanMoved(ni: Node.Index, mf: *const MappedFile) bool { + pub fn cleanMoved(ni: Node.Index, mf: *MappedFile) bool { const node_moved = &ni.get(mf).flags.moved; defer node_moved.* = false; return node_moved.*; @@ -242,7 +263,11 @@ pub const Node = extern struct { if (ni.hasMoved(mf)) return; const node = ni.get(mf); node.flags.moved = true; - if (node.flags.resized) return; + switch (node.prev) { + .none => {}, + else => |prev_ni| prev_ni.nextMovedAssumeCapacity(mf), + } + if (node.flags.resized or node.flags.next_moved) return; mf.updates.appendAssumeCapacity(ni); mf.update_prog_node.increaseEstimatedTotalItems(1); } @@ -250,11 +275,11 @@ pub const Node = extern struct { pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool { return ni.get(mf).flags.resized; } - pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void { + pub fn resized(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { try mf.updates.ensureUnusedCapacity(gpa, 1); ni.resizedAssumeCapacity(mf); } - pub fn cleanResized(ni: Node.Index, mf: *const MappedFile) bool { + pub fn cleanResized(ni: Node.Index, mf: *MappedFile) bool { const node_resized = &ni.get(mf).flags.resized; defer node_resized.* = false; return node_resized.*; @@ -263,7 +288,28 @@ pub const Node = extern struct { const node = ni.get(mf); if (node.flags.resized) return; node.flags.resized = true; - if (node.flags.moved) return; + if (node.flags.moved or node.flags.next_moved) return; + mf.updates.appendAssumeCapacity(ni); + mf.update_prog_node.increaseEstimatedTotalItems(1); + } + + pub fn hasNextMoved(ni: Node.Index, mf: *const MappedFile) bool { + return ni.get(mf).flags.next_moved; + } + pub fn nextMoved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { + try mf.updates.ensureUnusedCapacity(gpa, 1); + ni.nextMovedAssumeCapacity(mf); + } + pub fn cleanNextMoved(ni: Node.Index, mf: *MappedFile) bool { + const node_next_moved = &ni.get(mf).flags.next_moved; + defer node_next_moved.* = false; + return node_next_moved.*; + } + pub fn nextMovedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { + const node = ni.get(mf); + if (!node.flags.enable_next_moved or node.flags.next_moved) return; + node.flags.next_moved = true; + if (node.flags.moved or node.flags.resized) return; mf.updates.appendAssumeCapacity(ni); mf.update_prog_node.increaseEstimatedTotalItems(1); } @@ -333,7 +379,7 @@ pub const Node = extern struct { return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; } - pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) Error!void { + pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: Allocator, size: u64) Error!void { mf.resizeNode(gpa, ni, size) catch |err| switch (err) { error.OutOfMemory, error.Canceled, @@ -360,7 +406,7 @@ pub const Node = extern struct { pub fn realign( ni: Node.Index, mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, new_alignment: std.mem.Alignment, opts: RealignNodeOptions, ) Error!void { @@ -384,7 +430,7 @@ pub const Node = extern struct { pub fn shrink( ni: Node.Index, mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, size: u64, shift_next: bool, ) Error!void { @@ -392,7 +438,7 @@ pub const Node = extern struct { mf.updateWriters(); } - pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void { + pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: Allocator, w: *Writer) void { w.* = .{ .gpa = gpa, .mf = mf, @@ -419,7 +465,7 @@ pub const Node = extern struct { } pub const Writer = struct { - gpa: std.mem.Allocator, + gpa: Allocator, mf: *MappedFile, writer_node: std.SinglyLinkedList.Node, ni: Node.Index, @@ -543,14 +589,13 @@ pub const Node = extern struct { } }; -fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { +fn addNode(mf: *MappedFile, gpa: Allocator, opts: struct { parent: Node.Index = .none, prev: Node.Index = .none, next: Node.Index = .none, offset: u64 = 0, add_node: AddNodeOptions, }) (Allocator.Error || Io.Cancelable || IoError)!Node.Index { - if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1); mf.nodes_lock.assertUnlocked(); const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: { if (std.math.cast(u32, opts.offset)) |small_offset| break :location .{ .small, .{ @@ -570,7 +615,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { }; switch (opts.prev) { .none => opts.parent.get(mf).first = free_ni, - else => |prev_ni| prev_ni.get(mf).next = free_ni, + else => |prev_ni| try prev_ni.setNext(gpa, free_ni, mf), } switch (opts.next) { .none => opts.parent.get(mf).last = free_ni, @@ -588,22 +633,27 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { .fixed = opts.add_node.fixed, .moved = true, .resized = true, + .next_moved = true, .has_content = false, .bubbles_moved = opts.add_node.bubbles_moved, + .enable_next_moved = opts.add_node.enable_next_moved, }, .location_payload = location_payload, }; { + defer { + free_node.flags.moved = false; + free_node.flags.resized = false; + free_node.flags.next_moved = false; + } try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{}); try mf.resizeNode(gpa, free_ni, opts.add_node.size); - if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1); - free_node.flags.moved = false; - free_node.flags.resized = false; } - if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf); - if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf); mf.updateWriters(); + if (opts.add_node.moved) try free_ni.moved(gpa, mf); + if (opts.add_node.resized) try free_ni.resized(gpa, mf); + if (opts.add_node.next_moved) try free_ni.nextMoved(gpa, mf); return free_ni; } @@ -613,12 +663,14 @@ pub const AddNodeOptions = struct { fixed: bool = false, moved: bool = false, resized: bool = false, + next_moved: bool = false, bubbles_moved: bool = true, + enable_next_moved: bool = false, }; pub fn addOnlyChildNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, parent_ni: Node.Index, opts: AddNodeOptions, ) Error!Node.Index { @@ -641,7 +693,7 @@ pub fn addOnlyChildNode( pub fn addFirstChildNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, parent_ni: Node.Index, opts: AddNodeOptions, ) Error!Node.Index { @@ -664,7 +716,7 @@ pub fn addFirstChildNode( pub fn addLastChildNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, parent_ni: Node.Index, opts: AddNodeOptions, ) Error!Node.Index { @@ -694,7 +746,7 @@ pub fn addLastChildNode( pub fn addNodeAfter( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, prev_ni: Node.Index, opts: AddNodeOptions, ) Error!Node.Index { @@ -721,7 +773,7 @@ pub fn addNodeAfter( fn shrinkNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, ni: Node.Index, size: u64, shift_next: bool, @@ -740,7 +792,7 @@ fn shrinkNode( } try mf.large.ensureUnusedCapacity(gpa, 4); - try mf.updates.ensureUnusedCapacity(gpa, 2); + try mf.updates.ensureUnusedCapacity(gpa, 4); ni.setLocationAssumeCapacity(mf, old_offset, size); if (!shift_next or node.next == .none) return; @@ -765,7 +817,7 @@ fn shrinkNode( fn resizeNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, ni: Node.Index, requested_size: u64, ) (Allocator.Error || Io.Cancelable || IoError)!void { @@ -904,11 +956,11 @@ fn resizeNode( next_ni.get(mf).prev = node.prev; switch (node.prev) { .none => parent.first = next_ni, - else => |prev_ni| prev_ni.get(mf).next = next_ni, + else => |prev_ni| try prev_ni.setNext(gpa, next_ni, mf), } - last.next = ni; + try parent.last.setNext(gpa, ni, mf); node.prev = parent.last; - node.next = .none; + try ni.setNext(gpa, .none, mf); parent.last = ni; if (node.flags.has_content) { const parent_file_offset = node.parent.fileLocation(mf, false).offset; @@ -972,13 +1024,13 @@ fn resizeNode( if (parent.last != first_floating_ni) { first_floating.prev = parent.last; parent.last = first_floating_ni; - last.next = first_floating_ni; - last_fixed.next = first_floating.next; + try parent.last.setNext(gpa, first_floating_ni, mf); + try last_fixed_ni.setNext(gpa, first_floating.next, mf); switch (first_floating.next) { .none => {}, else => |next_ni| next_ni.get(mf).prev = last_fixed_ni, } - first_floating.next = .none; + try first_floating_ni.setNext(gpa, .none, mf); } if (first_floating.flags.has_content) { const parent_file_offset = @@ -1040,7 +1092,7 @@ fn resizeNode( fn realignNode( mf: *MappedFile, - gpa: std.mem.Allocator, + gpa: Allocator, ni: Node.Index, new_alignment: std.mem.Alignment, opts: Node.Index.RealignNodeOptions, @@ -1241,9 +1293,9 @@ fn copyFileRange( return size - remaining_size; } -fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void { +fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: Allocator) Allocator.Error!void { try mf.large.ensureUnusedCapacity(gpa, 2); - try mf.updates.ensureUnusedCapacity(gpa, 1); + try mf.updates.ensureUnusedCapacity(gpa, 2); } pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) Error!void { -- 2.54.0 From 63cb57eb31acc7d250b624b5d4501ebb6e969213 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 11 Jul 2026 21:56:30 -0400 Subject: [PATCH 040/215] x86_64: fix typo in calling convention handling Closes #36038 --- src/codegen/x86_64/CodeGen.zig | 2 +- test/c_abi/cfuncs.c | 210 +++++++++++++++++++++++++++--- test/c_abi/main.zig | 226 +++++++++++++++++++++++++++++---- 3 files changed, 396 insertions(+), 42 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index da0ace1f6dd5fe09e00eaf3c7e5b572de2d2e50a..2c7e0e3464fe10803470ac2eae19efaa9f9ffb11 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -181994,7 +181994,7 @@ fn resolveCallingConventionValues( } const save_param_gpr_index = param_gpr_index; - const save_param_sse_index = param_gpr_index; + const save_param_sse_index = param_sse_index; var arg_mcv: [4]MCValue = undefined; var arg_mcv_len: u32 = 0; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 302503ad4d839449c9aad546e712f3ebb6bdff3d..2013a36f2e379137dc1d61243f6b8222f4677b57 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -191,9 +191,6 @@ void zig_struct_i128(struct i128); #endif void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); -void zig_f32(float); -void zig_f64(double); -void zig_longdouble(long double); void zig_five_floats(float, float, float, float, float); bool zig_ret_bool(); @@ -219,6 +216,198 @@ float complex zig_cmultf(float complex a, float complex b); double complex zig_cmultd(double complex a, double complex b); #endif +float zig_ret_f32(void); +void zig_f32(float, size_t); +void zig_1_f32(size_t, float, size_t); +void zig_2_f32(size_t, size_t, float, size_t); +void zig_3_f32(size_t, size_t, size_t, float, size_t); +void zig_4_f32(size_t, size_t, size_t, size_t, float, size_t); +void zig_5_f32(size_t, size_t, size_t, size_t, size_t, float, size_t); +void zig_6_f32(size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); +void zig_7_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); +void zig_8_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); + +float c_ret_f32(void) { + return 11; +} +void c_f32(float f, size_t i) { + assert_or_panic(f == 12); + assert_or_panic(i == 1); +} +void c_1_f32(size_t a0, float f, size_t i) { + assert_or_panic(f == 13); + assert_or_panic(i == 2); +} +void c_2_f32(size_t a0, size_t a1, float f, size_t i) { + assert_or_panic(f == 14); + assert_or_panic(i == 3); +} +void c_3_f32(size_t a0, size_t a1, size_t a2, float f, size_t i) { + assert_or_panic(f == 15); + assert_or_panic(i == 4); +} +void c_4_f32(size_t a0, size_t a1, size_t a2, size_t a3, float f, size_t i) { + assert_or_panic(f == 16); + assert_or_panic(i == 5); +} +void c_5_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, float f, size_t i) { + assert_or_panic(f == 17); + assert_or_panic(i == 6); +} +void c_6_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, float f, size_t i) { + assert_or_panic(f == 18); + assert_or_panic(i == 7); +} +void c_7_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, float f, size_t i) { + assert_or_panic(f == 19); + assert_or_panic(i == 8); +} +void c_8_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, float f, size_t i) { + assert_or_panic(f == 20); + assert_or_panic(i == 9); +} +void c_test_f32(void) { + float f = zig_ret_f32(); + assert_or_panic(f == 1); + zig_f32(2, 1); + zig_1_f32(0, 3, 2); + zig_2_f32(0, 1, 4, 3); + zig_3_f32(0, 1, 2, 5, 4); + zig_4_f32(0, 1, 2, 3, 6, 5); + zig_5_f32(0, 1, 2, 3, 4, 7, 6); + zig_6_f32(0, 1, 2, 3, 4, 5, 8, 7); + zig_7_f32(0, 1, 2, 3, 4, 5, 6, 9, 8); + zig_8_f32(0, 1, 2, 3, 4, 5, 6, 7, 10, 9); +} + +double zig_ret_f64(void); +void zig_f64(double, size_t); +void zig_1_f64(size_t, double, size_t); +void zig_2_f64(size_t, size_t, double, size_t); +void zig_3_f64(size_t, size_t, size_t, double, size_t); +void zig_4_f64(size_t, size_t, size_t, size_t, double, size_t); +void zig_5_f64(size_t, size_t, size_t, size_t, size_t, double, size_t); +void zig_6_f64(size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); +void zig_7_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); +void zig_8_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); + +double c_ret_f64(void) { + return 11; +} +void c_f64(double f, size_t i) { + assert_or_panic(f == 12); + assert_or_panic(i == 1); +} +void c_1_f64(size_t a0, double f, size_t i) { + assert_or_panic(f == 13); + assert_or_panic(i == 2); +} +void c_2_f64(size_t a0, size_t a1, double f, size_t i) { + assert_or_panic(f == 14); + assert_or_panic(i == 3); +} +void c_3_f64(size_t a0, size_t a1, size_t a2, double f, size_t i) { + assert_or_panic(f == 15); + assert_or_panic(i == 4); +} +void c_4_f64(size_t a0, size_t a1, size_t a2, size_t a3, double f, size_t i) { + assert_or_panic(f == 16); + assert_or_panic(i == 5); +} +void c_5_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, double f, size_t i) { + assert_or_panic(f == 17); + assert_or_panic(i == 6); +} +void c_6_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, double f, size_t i) { + assert_or_panic(f == 18); + assert_or_panic(i == 7); +} +void c_7_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, double f, size_t i) { + assert_or_panic(f == 19); + assert_or_panic(i == 8); +} +void c_8_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, double f, size_t i) { + assert_or_panic(f == 20); + assert_or_panic(i == 9); +} +void c_test_f64(void) { + double f = zig_ret_f64(); + assert_or_panic(f == 1); + zig_f64(2, 1); + zig_1_f64(0, 3, 2); + zig_2_f64(0, 1, 4, 3); + zig_3_f64(0, 1, 2, 5, 4); + zig_4_f64(0, 1, 2, 3, 6, 5); + zig_5_f64(0, 1, 2, 3, 4, 7, 6); + zig_6_f64(0, 1, 2, 3, 4, 5, 8, 7); + zig_7_f64(0, 1, 2, 3, 4, 5, 6, 9, 8); + zig_8_f64(0, 1, 2, 3, 4, 5, 6, 7, 10, 9); +} + +long double zig_ret_longdouble(void); +void zig_longdouble(long double, size_t); +void zig_1_longdouble(size_t, long double, size_t); +void zig_2_longdouble(size_t, size_t, long double, size_t); +void zig_3_longdouble(size_t, size_t, size_t, long double, size_t); +void zig_4_longdouble(size_t, size_t, size_t, size_t, long double, size_t); +void zig_5_longdouble(size_t, size_t, size_t, size_t, size_t, long double, size_t); +void zig_6_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); +void zig_7_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); +void zig_8_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); + +long double c_ret_longdouble(void) { + return 11; +} +void c_longdouble(long double f, size_t i) { + assert_or_panic(f == 12); + assert_or_panic(i == 1); +} +void c_1_longdouble(size_t a0, long double f, size_t i) { + assert_or_panic(f == 13); + assert_or_panic(i == 2); +} +void c_2_longdouble(size_t a0, size_t a1, long double f, size_t i) { + assert_or_panic(f == 14); + assert_or_panic(i == 3); +} +void c_3_longdouble(size_t a0, size_t a1, size_t a2, long double f, size_t i) { + assert_or_panic(f == 15); + assert_or_panic(i == 4); +} +void c_4_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, long double f, size_t i) { + assert_or_panic(f == 16); + assert_or_panic(i == 5); +} +void c_5_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, long double f, size_t i) { + assert_or_panic(f == 17); + assert_or_panic(i == 6); +} +void c_6_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, long double f, size_t i) { + assert_or_panic(f == 18); + assert_or_panic(i == 7); +} +void c_7_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, long double f, size_t i) { + assert_or_panic(f == 19); + assert_or_panic(i == 8); +} +void c_8_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, long double f, size_t i) { + assert_or_panic(f == 20); + assert_or_panic(i == 9); +} +void c_test_longdouble(void) { + long double f = zig_ret_longdouble(); + assert_or_panic(f == 1); + zig_longdouble(2, 1); + zig_1_longdouble(0, 3, 2); + zig_2_longdouble(0, 1, 4, 3); + zig_3_longdouble(0, 1, 2, 5, 4); + zig_4_longdouble(0, 1, 2, 3, 6, 5); + zig_5_longdouble(0, 1, 2, 3, 4, 7, 6); + zig_6_longdouble(0, 1, 2, 3, 4, 5, 8, 7); + zig_7_longdouble(0, 1, 2, 3, 4, 5, 6, 9, 8); + zig_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 10, 9); +} + #if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__) typedef bool Vector_2_bool __attribute__((ext_vector_type(2))); @@ -15326,9 +15515,6 @@ void run_c_tests(void) { zig_five_integers(12, 34, 56, 78, 90); - zig_f32(12.34f); - zig_f64(56.78); - zig_longdouble(12.34l); zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); zig_ptr((void *)0xdeadbeefL); @@ -15550,18 +15736,6 @@ void c_struct_i128(struct i128 x) { } #endif -void c_f32(float x) { - assert_or_panic(x == 12.34f); -} - -void c_f64(double x) { - assert_or_panic(x == 56.78); -} - -void c_long_double(long double x) { - assert_or_panic(x == 12.34l); -} - void c_ptr(void *x) { assert_or_panic(x == (void *)0xdeadbeefL); } diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f9a48477a714b250696652184e1511ccf86bae28..f494b51818c33466614e24eb0efb398abb157779 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -104,10 +104,6 @@ export fn zig_struct_u128(a: U128) void { expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128"); } -extern fn c_f32(f32) void; -extern fn c_f64(f64) void; -extern fn c_long_double(c_longdouble) void; - // On windows x64, the first 4 are passed via registers, others on the stack. extern fn c_five_floats(f32, f32, f32, f32, f32) void; @@ -120,28 +116,9 @@ export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void { } test "floats" { - c_f32(12.34); - c_f64(56.78); c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0); } -test "long double" { - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - - c_long_double(12.34); -} - -export fn zig_f32(x: f32) void { - expect(x == 12.34) catch @panic("test failure: zig_f32"); -} -export fn zig_f64(x: f64) void { - expect(x == 56.78) catch @panic("test failure: zig_f64"); -} -export fn zig_longdouble(x: c_longdouble) void { - if (!builtin.target.cpu.arch.isWasm()) return; // waiting for #1481 - expect(x == 12.34) catch @panic("test failure: zig_longdouble"); -} - extern fn c_ptr(*anyopaque) void; test "pointer" { @@ -269,6 +246,209 @@ export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble return .{ .real = 1.5, .imag = 13.5 }; } +export fn zig_ret_f32() f32 { + return 1; +} +export fn zig_f32(f: f32, i: usize) void { + expect(f == 2) catch @panic("test failure"); + expect(i == 1) catch @panic("test failure"); +} +export fn zig_1_f32(_: usize, f: f32, i: usize) void { + expect(f == 3) catch @panic("test failure"); + expect(i == 2) catch @panic("test failure"); +} +export fn zig_2_f32(_: usize, _: usize, f: f32, i: usize) void { + expect(f == 4) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); +} +export fn zig_3_f32(_: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 5) catch @panic("test failure"); + expect(i == 4) catch @panic("test failure"); +} +export fn zig_4_f32(_: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 6) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} +export fn zig_5_f32(_: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 7) catch @panic("test failure"); + expect(i == 6) catch @panic("test failure"); +} +export fn zig_6_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 8) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} +export fn zig_7_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 9) catch @panic("test failure"); + expect(i == 8) catch @panic("test failure"); +} +export fn zig_8_f32(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f32, i: usize) void { + expect(f == 10) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_f32() f32; +extern fn c_f32(f32, usize) void; +extern fn c_1_f32(usize, f32, usize) void; +extern fn c_2_f32(usize, usize, f32, usize) void; +extern fn c_3_f32(usize, usize, usize, f32, usize) void; +extern fn c_4_f32(usize, usize, usize, usize, f32, usize) void; +extern fn c_5_f32(usize, usize, usize, usize, usize, f32, usize) void; +extern fn c_6_f32(usize, usize, usize, usize, usize, usize, f32, usize) void; +extern fn c_7_f32(usize, usize, usize, usize, usize, usize, usize, f32, usize) void; +extern fn c_8_f32(usize, usize, usize, usize, usize, usize, usize, usize, f32, usize) void; +extern fn c_test_f32() void; + +test "f32" { + const f = c_ret_f32(); + try expect(f == 11); + c_f32(12, 1); + c_1_f32(0, 13, 2); + c_2_f32(0, 1, 14, 3); + c_3_f32(0, 1, 2, 15, 4); + c_4_f32(0, 1, 2, 3, 16, 5); + c_5_f32(0, 1, 2, 3, 4, 17, 6); + c_6_f32(0, 1, 2, 3, 4, 5, 18, 7); + c_7_f32(0, 1, 2, 3, 4, 5, 6, 19, 8); + c_8_f32(0, 1, 2, 3, 4, 5, 6, 7, 20, 9); + c_test_f32(); +} + +export fn zig_ret_f64() f64 { + return 1; +} +export fn zig_f64(f: f64, i: usize) void { + expect(f == 2) catch @panic("test failure"); + expect(i == 1) catch @panic("test failure"); +} +export fn zig_1_f64(_: usize, f: f64, i: usize) void { + expect(f == 3) catch @panic("test failure"); + expect(i == 2) catch @panic("test failure"); +} +export fn zig_2_f64(_: usize, _: usize, f: f64, i: usize) void { + expect(f == 4) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); +} +export fn zig_3_f64(_: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 5) catch @panic("test failure"); + expect(i == 4) catch @panic("test failure"); +} +export fn zig_4_f64(_: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 6) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} +export fn zig_5_f64(_: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 7) catch @panic("test failure"); + expect(i == 6) catch @panic("test failure"); +} +export fn zig_6_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 8) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} +export fn zig_7_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 9) catch @panic("test failure"); + expect(i == 8) catch @panic("test failure"); +} +export fn zig_8_f64(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: f64, i: usize) void { + expect(f == 10) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_f64() f64; +extern fn c_f64(f64, usize) void; +extern fn c_1_f64(usize, f64, usize) void; +extern fn c_2_f64(usize, usize, f64, usize) void; +extern fn c_3_f64(usize, usize, usize, f64, usize) void; +extern fn c_4_f64(usize, usize, usize, usize, f64, usize) void; +extern fn c_5_f64(usize, usize, usize, usize, usize, f64, usize) void; +extern fn c_6_f64(usize, usize, usize, usize, usize, usize, f64, usize) void; +extern fn c_7_f64(usize, usize, usize, usize, usize, usize, usize, f64, usize) void; +extern fn c_8_f64(usize, usize, usize, usize, usize, usize, usize, usize, f64, usize) void; +extern fn c_test_f64() void; + +test "f64" { + const f = c_ret_f64(); + try expect(f == 11); + c_f64(12, 1); + c_1_f64(0, 13, 2); + c_2_f64(0, 1, 14, 3); + c_3_f64(0, 1, 2, 15, 4); + c_4_f64(0, 1, 2, 3, 16, 5); + c_5_f64(0, 1, 2, 3, 4, 17, 6); + c_6_f64(0, 1, 2, 3, 4, 5, 18, 7); + c_7_f64(0, 1, 2, 3, 4, 5, 6, 19, 8); + c_8_f64(0, 1, 2, 3, 4, 5, 6, 7, 20, 9); + c_test_f64(); +} + +export fn zig_ret_longdouble() c_longdouble { + return 1; +} +export fn zig_longdouble(f: c_longdouble, i: usize) void { + expect(f == 2) catch @panic("test failure"); + expect(i == 1) catch @panic("test failure"); +} +export fn zig_1_longdouble(_: usize, f: c_longdouble, i: usize) void { + expect(f == 3) catch @panic("test failure"); + expect(i == 2) catch @panic("test failure"); +} +export fn zig_2_longdouble(_: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 4) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); +} +export fn zig_3_longdouble(_: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 5) catch @panic("test failure"); + expect(i == 4) catch @panic("test failure"); +} +export fn zig_4_longdouble(_: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 6) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} +export fn zig_5_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 7) catch @panic("test failure"); + expect(i == 6) catch @panic("test failure"); +} +export fn zig_6_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 8) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} +export fn zig_7_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 9) catch @panic("test failure"); + expect(i == 8) catch @panic("test failure"); +} +export fn zig_8_longdouble(_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, f: c_longdouble, i: usize) void { + expect(f == 10) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_longdouble() c_longdouble; +extern fn @"c_longdouble"(c_longdouble, usize) void; +extern fn c_1_longdouble(usize, c_longdouble, usize) void; +extern fn c_2_longdouble(usize, usize, c_longdouble, usize) void; +extern fn c_3_longdouble(usize, usize, usize, c_longdouble, usize) void; +extern fn c_4_longdouble(usize, usize, usize, usize, c_longdouble, usize) void; +extern fn c_5_longdouble(usize, usize, usize, usize, usize, c_longdouble, usize) void; +extern fn c_6_longdouble(usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; +extern fn c_7_longdouble(usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; +extern fn c_8_longdouble(usize, usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; +extern fn c_test_longdouble() void; + +test "long double" { + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + + const f = c_ret_longdouble(); + try expect(f == 11); + @"c_longdouble"(12, 1); + c_1_longdouble(0, 13, 2); + c_2_longdouble(0, 1, 14, 3); + c_3_longdouble(0, 1, 2, 15, 4); + c_4_longdouble(0, 1, 2, 3, 16, 5); + c_5_longdouble(0, 1, 2, 3, 4, 17, 6); + c_6_longdouble(0, 1, 2, 3, 4, 5, 18, 7); + c_7_longdouble(0, 1, 2, 3, 4, 5, 6, 19, 8); + c_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 20, 9); + c_test_longdouble(); +} + comptime { skip: { if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; -- 2.54.0 From d01609af2aaf5a3c9ddd2ddf75a5d211e0e94b07 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 11 Jul 2026 22:25:43 -0400 Subject: [PATCH 041/215] x86_64: revert regression from #35865 Closes #35910 --- src/codegen/x86_64/CodeGen.zig | 18 ++++++++++++++---- test/c_abi/cfuncs.c | 9 +++++++-- test/c_abi/main.zig | 10 +++++++++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 2c7e0e3464fe10803470ac2eae19efaa9f9ffb11..d499ef406fc67f0a7a4fe8c81390b6ad434a36a5 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -176621,10 +176621,20 @@ fn genCall(cg: *CodeGen, info: union(enum) { for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) { .none, .load_frame, .indirect_load_frame => {}, - .register => |dst_reg| try cg.genSetReg(registerAlias( - dst_reg, - @intCast(cg.unalignedSize(arg_ty)), - ), arg_ty, src_arg, opts), + .register => |dst_reg| switch (fn_info.cc) { + else => try cg.genSetReg(registerAlias( + dst_reg, + @intCast(cg.unalignedSize(arg_ty)), + ), arg_ty, src_arg, opts), + .x86_64_sysv, .x86_64_win => { + const promoted_ty = cg.promoteInt(arg_ty); + const promoted_unaligned_size: u32 = @intCast(cg.unalignedSize(promoted_ty)); + const dst_alias = registerAlias(dst_reg, promoted_unaligned_size); + try cg.genSetReg(dst_alias, promoted_ty, src_arg, opts); + if (promoted_ty.toIntern() != arg_ty.toIntern()) + try cg.truncateRegister(arg_ty, dst_alias); + }, + }, .register_pair, .register_triple, .register_quadruple, diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 2013a36f2e379137dc1d61243f6b8222f4677b57..cfd3872c94ef750e6663f6e9c4d186516c76beb7 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -16386,7 +16386,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo } #endif -#if defined(__x86_64__) && defined(_WIN64) +void c_x86_64_sysv_uint_int_uint_int(unsigned a, int b, unsigned c, int d) { + assert_or_panic(a == 1); + assert_or_panic(b == -2); + assert_or_panic(c == 3); + assert_or_panic(d == -4); +} + void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) { assert_or_panic(a == UINT64_C(0x3ff0000000000000)); assert_or_panic(b == 2.0); @@ -16399,4 +16405,3 @@ void c_win64_varargs_f64_u64_f64_u64(double a, uint64_t b, double c, uint64_t d) assert_or_panic(c == 7.0); assert_or_panic(d == UINT64_C(0x4020000000000000)); } -#endif diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f494b51818c33466614e24eb0efb398abb157779..974adf898c9fd092396d279bf34a22f050235d73 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -17448,11 +17448,19 @@ test "x86 vectorcall calling convention" { static.c_vectorcall_check(1, 2.0, 3.0, @ptrFromInt(4), 5.0, 6.0, 7.0, 8.0, 9.0, 10); } +extern fn c_x86_64_sysv_uint_int_uint_int(a: u8, b: i8, c: u16, d: i16) void; + +test "x86_64 sysv args" { + if (std.lang.CallingConvention.c != .x86_64_sysv) return error.SkipZigTest; + + c_x86_64_sysv_uint_int_uint_int(1, -2, 3, -4); +} + extern fn c_win64_varargs_u64_f64_u64_f64(...) void; extern fn c_win64_varargs_f64_u64_f64_u64(...) void; test "win64 varargs" { - if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .windows) return error.SkipZigTest; + if (std.lang.CallingConvention.c != .x86_64_win) return error.SkipZigTest; const Opv = extern struct {}; c_win64_varargs_u64_f64_u64_f64( -- 2.54.0 From 897c0b35a92dba851edd2ce49314468d3e1fcaff Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 28 Jun 2026 15:19:23 -0400 Subject: [PATCH 042/215] Revert "cbe: improve struct/union defs on 32-bit targets" This reverts commit 5434f85c47f6412a8d5faf681419c15533bb388c, which was just hacking around other bugs. --- src/Type.zig | 2 +- src/codegen/c/type/render_defs.zig | 88 ++++++++++-------------------- 2 files changed, 29 insertions(+), 61 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index e60726ced3ff48df988eff1505786071c596ff2a..32e49a05c26a8ee5459164c02f987c92704f0f65 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -962,7 +962,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { const bytes = ((elem_bits * vector_type.len) + 7) / 8; return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); }, - .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).defaultStructFieldAlignment(.auto, zcu), + .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu), .stage2_x86_64 => { if (vector_type.child == .bool_type) { if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64"; diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index 03aae41ee0ec47cca9b560bd358263a5b0cb2352..866ea38cc44be5a44e0dba9aa6c75cf989cb664b 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -284,9 +284,8 @@ pub fn defineComplete( }, }, .array => if (ty.hasRuntimeBits(zcu)) { - const elem_ty = ty.childType(zcu); const name_cty: CType = .{ .arr = ty }; - const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu); + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); const array_cty: CType = .{ .array = .{ .len = ty.arrayLenIncludingSentinel(zcu), .elem_ty = &elem_cty, @@ -296,28 +295,17 @@ pub fn defineComplete( break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); }, } }; - if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) { - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ - name_cty.fmtTypeName(zcu), - array_cty.fmtDeclaratorPrefix(zcu), - array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), - }); - } else { - try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{ - name_cty.fmtTypeName(zcu), - elem_ty.abiAlignment(zcu).toByteUnits().?, - array_cty.fmtDeclaratorPrefix(zcu), - array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), - }); - } + try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + array_cty.fmtDeclaratorPrefix(zcu), + array_cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); try writeStaticAssertLayout(ty, name_cty, w, zcu); }, .vector => if (ty.hasRuntimeBits(zcu)) { - const elem_ty = ty.childType(zcu); const name_cty: CType = .{ .vec = ty }; - const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu); + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); const array_cty: CType = .{ .array = .{ .len = ty.arrayLenIncludingSentinel(zcu), .elem_ty = &elem_cty, @@ -363,39 +351,21 @@ fn defineTuple( const ip = &zcu.intern_pool; const tuple = ip.indexToKey(ty.toIntern()).tuple_type; + // Fields cannot be underaligned, because tuple fields cannot have specified alignments. + // However, overaligned fields are possible thanks to intermediate zero-bit fields. + const tuple_align = ty.abiAlignment(zcu); - // If there are any underaligned fields, we need to byte-pack the tuple. - const pack: bool = pack: { - var offset: u64 = 0; - for (tuple.types.get(ip)) |field_ty_ip| { - const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); - const natural_offset = natural_align.forward(offset); - offset = field_ty.abiAlignment(zcu).forward(offset); - if (offset < natural_offset) break :pack true; - // Also pack if any field is more aligned than the tuple should be. - if (natural_align.compareStrict(.gt, tuple_align)) break :pack true; - offset += field_ty.abiSize(zcu); - } - break :pack false; - }; - // If the alignment of other fields would not give the tuple sufficient alignment, we // need to align the first field (which does not affect its offset, because 0 is always // well-aligned) to indirectly specify the tuple alignment. - const overalign: bool = switch (pack) { - true => tuple_align.compareStrict(.gt, .@"1"), - false => for (tuple.types.get(ip)) |field_ty_ip| { - const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); - if (natural_align.compareStrict(.gte, tuple_align)) break false; - } else true, - }; + const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + if (natural_align.compareStrict(.gte, tuple_align)) break false; + } else true; - if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .@"struct" = ty }; try w.print("{f} {{ /* {f} */\n", .{ name_cty.fmtTypeName(zcu), @@ -406,18 +376,18 @@ fn defineTuple( for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| { if (field_val_ip != .none) continue; // `comptime` field const field_ty: Type = .fromInterned(field_ty_ip); - zig_offset = field_ty.abiAlignment(zcu).forward(zig_offset); + const field_align = field_ty.abiAlignment(zcu); + zig_offset = field_align.forward(zig_offset); if (!field_ty.hasRuntimeBits(zcu)) continue; - if (!pack) c_offset = field_ty.defaultStructFieldAlignment(.auto, zcu).forward(c_offset); + c_offset = field_align.forward(c_offset); try w.writeByte(' '); if (zig_offset == 0 and overalign) { // This is the first field; specify its alignment to align the tuple. try writeFieldAlign(field_ty, tuple_align, w, zcu); } else if (zig_offset > c_offset) { - // This field needs to be underaligned or overaligned compared to what its - // offset would otherwise be. + // This field needs to be overaligned compared to what its offset would otherwise be. const need_align: Alignment = .minStrict( - tuple_align, // don't make the tuple more aligned than it should be + tuple_align, // don't make the struct more aligned than it should be .fromLog2Units(@ctz(zig_offset)), ); try writeFieldAlign(field_ty, need_align, w, zcu); @@ -433,9 +403,7 @@ fn defineTuple( zig_offset += field_size; c_offset += field_size; } - try w.writeByte('}'); - if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); + try w.writeAll("};\n"); try writeStaticAssertLayout(ty, name_cty, w, zcu); } @@ -553,7 +521,7 @@ fn defineUnionAuto( const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gt, union_type.alignment)) break true; // The tag will immediately follow the payload. This layout may put the tag in what would // otherwise be padding on the payload union, because if the most-aligned union field is not @@ -571,7 +539,7 @@ fn defineUnionAuto( false => for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, union_type.alignment)) break false; } else overalign: { if (union_type.has_runtime_tag) { @@ -642,7 +610,7 @@ fn defineUnionExtern( const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gt, union_type.alignment)) break true; } else false; @@ -654,7 +622,7 @@ fn defineUnionExtern( false => for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, union_type.alignment)) break false; } else overalign: { if (union_type.has_runtime_tag) { @@ -704,7 +672,7 @@ fn writeFieldAlign( w: *Writer, zcu: *const Zcu, ) Writer.Error!void { - if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) { + if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); } else { try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}); -- 2.54.0 From 409c89ee2161c071ca713b5b69e8707b0e538aab Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 08:09:40 -0400 Subject: [PATCH 043/215] Compilation: avoid illegal behavior during create --- src/Compilation.zig | 3 +++ src/Zcu.zig | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/Compilation.zig b/src/Compilation.zig index d62856b0111be20def4ebf322ee0f58831995161..df6fc7b06b192553ca5faed923c4a9b4406814f5 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2134,6 +2134,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, comp.config.any_fuzz = any_fuzz; if (opt_zcu) |zcu| { + // Finish initializing the `zcu` after the fields on `comp` have been initialized. + zcu.initAfterCompilation(); + // Populate `zcu.module_roots`. const active = zcu.acquire(); defer active.release(); diff --git a/src/Zcu.zig b/src/Zcu.zig index d3c180b63eb8854ec8598cdb3099bba7a41fb2b3..d71d8ecf80ef074a1800c9d637744a023523fede 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2825,6 +2825,11 @@ pub const CompileError = error{ pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { try zcu.intern_pool.init(gpa, io, thread_count); +} + +/// It is valid to not call this function before `deinit` in error paths. +/// Requires the fields on `zcu.comp` to already be initialized. +pub fn initAfterCompilation(zcu: *Zcu) void { zcu.initTracyPlots(); } -- 2.54.0 From e26a70cb96bbdeb633314dec8afa9daf3029b894 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 04:19:58 -0400 Subject: [PATCH 044/215] main: minor improvement to testing with cbe --- src/main.zig | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 94011c81f9215df1da00328f221c41e42b9bc214..a7b8ddb6d08cac1dfd2b882f4dda65ec03c181d1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3835,11 +3835,17 @@ fn buildOutputType( var prev_has_cflags = false; var prev_has_rcflags = false; - if (dirs.zig_lib.path) |zig_lib_path| { - try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); - prev_has_cflags = true; + { + if (dirs.zig_lib.path) |zig_lib_path| { + try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); + prev_has_cflags = true; + } + const emit_ext: Compilation.FileExt = .c; + const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true; + if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() }); + try test_exec_args.append(arena, null); + if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" }); } - try test_exec_args.append(arena, null); for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| { for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| { const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len; -- 2.54.0 From 9e7f40db3a83242e12db853431cea0701446f5fb Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Tue, 23 Jun 2026 09:09:43 -0400 Subject: [PATCH 045/215] InternPool: update `Tag.encodings` to fix lldb pretty printing --- lib/std/hash_map.zig | 2 +- lib/std/multi_array_list.zig | 4 +-- src/InternPool.zig | 54 ++++++++++++++++++------------------ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index a6562bc5ea1ab479963b308beae24fb303d98c6d..b11f7e4a0dee9413d8ca5a798492c48f0ba5dde1 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -1518,7 +1518,7 @@ fn Custom( self.available = 0; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// header type to facilitate fancy debug printing for this type. fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void { _ = self; diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index a10f261e31ef8d4f47a976eebb3f637c199f835f..ce6265655eb690499577bc7fbd29c19eab375854 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -163,7 +163,7 @@ pub fn MultiArrayList(comptime T: type) type { }; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// child field order and entry type to facilitate fancy debug printing for this type. fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void { _ = self; @@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type { } break :entry @Struct(.@"extern", null, &entry_field_names, &entry_field_types, &entry_field_attrs); }; - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// child field order and entry type to facilitate fancy debug printing for this type. fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void { _ = self; diff --git a/src/InternPool.zig b/src/InternPool.zig index 5a28a997418a52a40a06c324d610348ab5c17800..8502055c372f2fb915be32133ee6a8be60916e4b 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4193,7 +4193,7 @@ pub const Index = enum(u32) { }; } - /// This function is used in the debugger pretty formatters in tools/ to fetch the + /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the /// Tag to encoding mapping to facilitate fancy debug printing for this type. fn dbHelper(self: *Index, tag_to_encoding_map: *struct { const DataIsIndex = struct { data: Index }; @@ -4219,26 +4219,17 @@ pub const Index = enum(u32) { type_inferred_error_set: DataIsIndex, simple_type: void, type_function: struct { - const @"data.flags.has_comptime_bits" = opaque {}; - const @"data.flags.has_noalias_bits" = opaque {}; - const @"data.flags.cc.extraLen()" = opaque {}; const @"data.params_len" = opaque {}; data: *Tag.TypeFunction, - @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits", - @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits", - @"trailing.cc_bits.len": *@"data.flags.cc.extraLen()", @"trailing.param_types.len": *@"data.params_len", - trailing: struct { comptime_bits: []u32, noalias_bits: []u32, cc_bits: []u32, param_types: []Index }, + trailing: struct { param_types: []Index }, }, type_tuple: struct { const @"data.fields_len" = opaque {}; data: *TypeTuple, @"trailing.types.len": *@"data.fields_len", @"trailing.values.len": *@"data.fields_len", - trailing: struct { - types: []Index, - values: []Index, - }, + trailing: struct { types: []Index, values: []Index }, }, type_struct: struct { data: *Tag.TypeStruct }, @@ -4350,7 +4341,7 @@ pub const Index = enum(u32) { const encoding = @field(Tag.encodings, tag_name); if (@hasField(@TypeOf(encoding), "trailing")) { const trailing_info = @typeInfo(encoding.trailing).@"struct"; - for (trailing_info.field_names, trailing_info.field_types) |field_name, field_type| { + for (trailing_info.field_names, trailing_info.field_types) |trailing_field_name, trailing_field_type| { struct { fn checkConfig(name: []const u8) void { if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\""); @@ -4359,22 +4350,30 @@ pub const Index = enum(u32) { } fn checkField(name: []const u8, Type: type) void { switch (@typeInfo(Type)) { - .int => {}, - .@"enum" => {}, - .@"struct" => |info| assert(info.layout == .@"packed"), + .int, .@"enum" => return, + .@"struct" => |info| switch (info.layout) { + .auto => unreachable, + .@"extern" => { + for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type); + return; + }, + .@"packed" => return, + }, .optional => |info| { checkConfig(name ++ ".?"); checkField(name ++ ".?", info.child); + return; }, - .pointer => |info| { - assert(info.size == .slice); + .pointer => |info| if (info.size == .slice) { checkConfig(name ++ ".len"); checkField(name ++ "[0]", info.child); + return; }, - else => @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)), + else => {}, } + @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)); } - }.checkField("trailing." ++ field_name, field_type); + }.checkField("trailing." ++ trailing_field_name, trailing_field_type); } } }, @@ -5186,17 +5185,18 @@ pub const Tag = enum(u8) { .trailing = struct { param_comptime_bits: ?[]u32, param_noalias_bits: ?[]u32, - param_cc_bits: ?[]u32, - param_type: []Index, + spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 }, + spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 }, + param_types: []Index, }, .config = .{ .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", - .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0", - .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()", - .@"trailing.param_type.len" = .@"payload.params_len", + .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task", + .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh", + .@"trailing.param_types.len" = .@"payload.params_len", }, }, @@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) { .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", .@"trailing.field_defaults.?.len" = .@"payload.fields_len", .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns", - .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", @@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) { .@"trailing.captures.?.len" = .@"trailing.captures_len.?", .@"trailing.field_types.len" = .@"payload.fields_len", .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns", - .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", }, }, .type_union_packed_auto = union_packed_encoding, -- 2.54.0 From c6ab46cc3effecd18db8b8469de965eafd02e1fd Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 26 Jun 2026 01:52:10 -0400 Subject: [PATCH 046/215] llvm: `TypeRepr.by_value` -> `TypeRepr.as_value` Otherwise, I constantly get it confused with `by_val` and `byval`. --- src/codegen/llvm.zig | 40 +++--- src/codegen/llvm/FuncGen.zig | 234 +++++++++++++++++------------------ 2 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 12422f9f6f8ba5609730e1f38e37960951409174..6d200cacafc52cc7067eefe18f07c1d1a9580768 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2848,7 +2848,7 @@ pub const Object = struct { pub const TypeRepr = enum { /// The representation of the type when it is being manipulated as a value in a function. /// e.g. Zig `u5` -> LLVM `i5` - by_value, + as_value, /// The representation of the type when it is stored in memory. /// e.g. Zig `u5` -> LLVM `i8` in_memory, @@ -2856,7 +2856,7 @@ pub const Object = struct { pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type { return o.builder.intType(switch (repr) { - .by_value => o.zcu.errorSetBits(), + .as_value => o.zcu.errorSetBits(), .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8), }); } @@ -2866,7 +2866,7 @@ pub const Object = struct { const target = zcu.getTarget(); const ip = &zcu.intern_pool; - if (repr == .by_value) { + if (repr == .as_value) { assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory } @@ -2886,7 +2886,7 @@ pub const Object = struct { .u128_type, .i128_type, => |tag| switch (repr) { - .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), + .as_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), }, .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), @@ -2973,7 +2973,7 @@ pub const Object = struct { => unreachable, else => switch (ip.indexToKey(t.toIntern())) { .int_type => |int_type| switch (repr) { - .by_value => try o.builder.intType(int_type.bits), + .as_value => try o.builder.intType(int_type.bits), .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), }, .ptr_type => |ptr_type| type: { @@ -2995,7 +2995,7 @@ pub const Object = struct { .vector_type => |vector_type| o.builder.vectorType( .normal, vector_type.len, - try o.lowerType(.fromInterned(vector_type.child), .by_value), + try o.lowerType(.fromInterned(vector_type.child), .as_value), ), .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. @@ -3310,7 +3310,7 @@ pub const Object = struct { .no_bits => continue, .byval => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value)); + try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); @@ -3325,7 +3325,7 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); try llvm_params.appendSlice(o.gpa, &.{ try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)), - try o.lowerType(.usize, .by_value), + try o.lowerType(.usize, .as_value), }); }, .multiple_llvm_types => { @@ -3347,7 +3347,7 @@ pub const Object = struct { const llvm_ret_ty: Builder.Type = switch (ret_strat) { .void, .sret => .void, - .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .by_value), + .by_val => try o.lowerType(.fromInterned(fn_info.return_type), .as_value), .mem_cast => |llvm_ret_ty| llvm_ret_ty, }; const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) { @@ -3604,7 +3604,7 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, .by_value); + result_val.* = try o.lowerValue(elem, .as_value); }, .repeated_elem => unreachable, } @@ -3612,7 +3612,7 @@ pub const Object = struct { }, .repeated_elem => |elem| return o.builder.splatConst( vector_ty, - try o.lowerValue(elem, .by_value), + try o.lowerValue(elem, .as_value), ), } }, @@ -3869,8 +3869,8 @@ pub const Object = struct { }, .int => try o.builder.castConst( .inttoptr, - try o.builder.intConst(try o.lowerType(.usize, .by_value), offset), - try o.lowerType(.fromInterned(ptr.ty), .by_value), + try o.builder.intConst(try o.lowerType(.usize, .as_value), offset), + try o.lowerType(.fromInterned(ptr.ty), .as_value), ), .eu_payload => |eu_ptr| try o.lowerPtr( eu_ptr, @@ -3917,7 +3917,7 @@ pub const Object = struct { @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { const addr: u64 = @"align".toByteUnits().?; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const llvm_addr = try o.builder.intConst(llvm_usize, addr); const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget())); return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty); @@ -4132,9 +4132,9 @@ pub const Object = struct { const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); - const llvm_usize_ty = try o.lowerType(.usize, .by_value); - const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value); - const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); + const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value); + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); @@ -4183,7 +4183,7 @@ pub const Object = struct { const return_block = try wip.block(1, "Name"); const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) { .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered - else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value), + else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value), }; try wip_switch.addCase(llvm_tag_val, return_block, &wip); @@ -4229,7 +4229,7 @@ pub const Object = struct { const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); - const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); @@ -4256,7 +4256,7 @@ pub const Object = struct { if (loaded_enum.field_values.len > 0) { for (loaded_enum.field_values.get(ip)) |tag_val_ip| { - const llvm_tag_val = try o.lowerValue(tag_val_ip, .by_value); + const llvm_tag_val = try o.lowerValue(tag_val_ip, .as_value); try wip_switch.addCase(llvm_tag_val, named_block, &wip); } } else { diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 6e2d71994a6f67a10a9aa7723071c419cd1815e4..5e05a779220d002a88fd128d5057f5eef70e1a4a 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -164,7 +164,7 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { const zcu = o.zcu; const ty = val.typeOf(zcu); if (!isByRef(ty, zcu)) { - return o.lowerValue(val.toIntern(), .by_value); + return o.lowerValue(val.toIntern(), .as_value); } else { // We need a pointer to a global constant, i.e. a UAV. return o.lowerUavRef( @@ -264,7 +264,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); assert(!isByRef(param_ty, zcu)); const slice_val = try fg.wip.buildAggregate( - try o.lowerType(param_ty, .by_value), + try o.lowerType(param_ty, .as_value), &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) }, "", ); @@ -998,7 +998,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, cc_info.llvm_cc, try attributes.finish(&o.builder), - try o.lowerType(zig_fn_ty, .by_value), + try o.lowerType(zig_fn_ty, .as_value), llvm_fn, llvm_args.items, "", @@ -1038,7 +1038,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v const target = zcu.getTarget(); const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl())); const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?; - const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .by_value); + const llvm_panic_fn_ty = try o.lowerType(.fromInterned(panic_func.ty), .as_value); const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav); @@ -1076,7 +1076,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo .none => try self.buildZigAlloca(ret_ty, .none), else => |rp| rp, }; - const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( rp, ret_ty_align.toLlvm(), @@ -1165,7 +1165,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const list = try self.resolveInst(ty_op.operand); const arg_ty = ty_op.ty.toType(); - const llvm_arg_ty = try self.object.lowerType(arg_ty, .by_value); + const llvm_arg_ty = try self.object.lowerType(arg_ty, .as_value); return self.wip.vaArg(list, llvm_arg_ty, ""); } @@ -1378,7 +1378,7 @@ fn lowerBlock( if (have_block_result) { const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) { true => .ptr, - false => try o.lowerType(inst_ty, .by_value), + false => try o.lowerType(inst_ty, .as_value), }; parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len); const phi = try self.wip.phi(llvm_ty, ""); @@ -1485,7 +1485,7 @@ fn lowerSwitchDispatch( const table_index = try self.wip.conv( .unsigned, try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""), - try o.lowerType(.usize, .by_value), + try o.lowerType(.usize, .as_value), "", ); const target_ptr_ptr = try self.ptraddScaled( @@ -1510,7 +1510,7 @@ fn lowerSwitchDispatch( // The switch prongs will correspond to our scalar cases. Ranges will // be handled by conditional branches in the `else` prong. - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer) try self.wip.cast(.ptrtoint, cond, llvm_usize, "") else @@ -1725,7 +1725,7 @@ fn lowerTry( if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, ); }; - const zero = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const zero = try o.builder.intValue(try o.errorIntType(.as_value), 0); const is_err = try fg.wip.icmp(.ne, loaded, zero, ""); const return_block = try fg.wip.block(1, "TryRet"); @@ -1862,8 +1862,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod const table_includes_else = item_count != table_len; break :jmp_table .{ - .min = try o.lowerValue(min.toIntern(), .by_value), - .max = try o.lowerValue(max.toIntern(), .by_value), + .min = try o.lowerValue(min.toIntern(), .as_value), + .max = try o.lowerValue(max.toIntern(), .as_value), .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) { .none, .cold => .none, .unpredictable => .unpredictable, @@ -2021,9 +2021,9 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); - const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .by_value); + const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst), .as_value); const operand = try self.resolveInst(ty_op.operand); return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } @@ -2040,7 +2040,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const target = zcu.getTarget(); if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( @@ -2108,7 +2108,7 @@ fn airIntFromFloat( const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag @@ -2142,7 +2142,7 @@ fn airIntFromFloat( compiler_rt_dest_abbrev, }); - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); var result = try self.wip.call( .normal, @@ -2167,7 +2167,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { const o = fg.object; const zcu = o.zcu; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); switch (ty.ptrSize(zcu)) { .slice => { const len = try fg.wip.extractValue(ptr, &.{1}, ""); @@ -2365,7 +2365,7 @@ fn airAggFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. }, .float => { // bitcast int->float - return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .by_value), ""); + return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty, .as_value), ""); }, } } @@ -2395,8 +2395,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); if (field_offset == 0) return field_ptr; - const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value); - const llvm_usize = try o.lowerType(.usize, .by_value); + const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); const base_ptr_int = try self.wip.bin( @@ -2612,7 +2612,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const output_inst = try self.resolveInst(output.operand); const output_ty = self.typeOf(output.operand); assert(output_ty.zigTypeTag(zcu) == .pointer); - const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .by_value); + const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu), .as_value); switch (constraint[0]) { '=' => {}, @@ -2650,7 +2650,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_ret_indirect[output.index] = false; const ret_ty = self.typeOfIndex(inst); - llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .by_value); + llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty, .as_value); llvm_ret_i += 1; } @@ -2689,7 +2689,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip); } else { const alignment = arg_ty.abiAlignment(zcu).toLlvm(); - const arg_llvm_ty = try o.lowerType(arg_ty, .by_value); + const arg_llvm_ty = try o.lowerType(arg_ty, .as_value); const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, ""); llvm_param_values[llvm_param_i] = load_inst; llvm_param_types[llvm_param_i] = arg_llvm_ty; @@ -2729,7 +2729,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); - break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .by_value); + break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu), .as_value); } else .none; llvm_param_i += 1; @@ -2743,7 +2743,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { if (constraint[0] != '+') continue; const rw_ty = self.typeOf(output.operand); - const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .by_value); + const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu), .as_value); if (llvm_ret_indirect[output.index]) { llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); @@ -2957,7 +2957,7 @@ fn airIsNonNull( )); return self.wip.icmp(cond, slice_ptr, try o.builder.nullValue(ptr_ty), ""); } - return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .by_value)), ""); + return self.wip.icmp(cond, loaded, try o.builder.zeroInitValue(try o.lowerType(optional_ty, .as_value)), ""); } comptime assert(optional_layout_version == 3); @@ -2986,7 +2986,7 @@ fn airIsErr( const operand_ty = self.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const zero_err = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const zero_err = try o.builder.intValue(try o.errorIntType(.as_value), 0); const access_kind: Builder.MemoryAccessKind = if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -3156,7 +3156,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); const payload_ty = err_union_ty.errorUnionPayload(zcu); - const non_error_val = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const non_error_val = try o.builder.intValue(try o.errorIntType(.as_value), 0); const access_kind: Builder.MemoryAccessKind = if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -3234,7 +3234,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error! const payload_ty = self.typeOf(ty_op.operand); assert(payload_ty.hasRuntimeBits(zcu)); assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref - const ok_err_code = try o.builder.intValue(try o.errorIntType(.by_value), 0); + const ok_err_code = try o.builder.intValue(try o.errorIntType(.as_value), 0); const result_ptr = try self.buildZigAlloca(err_un_ty, .none); @@ -3273,7 +3273,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; const index = pl_op.payload; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ try o.builder.intValue(.i32, index), }, ""); @@ -3283,7 +3283,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; const index = pl_op.payload; - const llvm_isize = try o.lowerType(.isize, .by_value); + const llvm_isize = try o.lowerType(.isize, .as_value); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), }, ""); @@ -3310,7 +3310,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smin else .umin, - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3330,7 +3330,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smax else .umax, - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3342,7 +3342,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr = try self.resolveInst(bin_op.lhs); const len = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .by_value), &.{ ptr, len }, ""); + return self.wip.buildAggregate(try self.object.lowerType(inst_ty, .as_value), &.{ ptr, len }, ""); } fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { @@ -3373,7 +3373,7 @@ fn airSafeArithmetic( const scalar_ty = inst_ty.scalarType(zcu); const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try o.lowerType(inst_ty, .by_value); + const llvm_inst_ty = try o.lowerType(inst_ty, .as_value); const results = try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); @@ -3423,7 +3423,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3462,7 +3462,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs }, "", ); @@ -3501,7 +3501,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat", - &.{try o.lowerType(inst_ty, .by_value)}, + &.{try o.lowerType(inst_ty, .as_value)}, &.{ lhs, rhs, .@"0" }, "", ); @@ -3545,8 +3545,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var bfa_buf: ExpectedContents = undefined; @@ -3594,8 +3594,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var bfa_buf: ExpectedContents = undefined; @@ -3634,8 +3634,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction"); return self.wip.bin(.@"add nsw", div, correction, "divCeil"); } else { - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const zero = try o.builder.splatValue( inst_llvm_ty, @@ -3692,7 +3692,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { @@ -3721,7 +3721,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo defer allocator.free(smin_big_int.limbs); smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits); const smin = try o.builder.splatValue(inst_llvm_ty, try o.builder.bigIntConst( - try o.lowerType(scalar_ty, .by_value), + try o.lowerType(scalar_ty, .as_value), smin_big_int.toConst(), )); @@ -3757,7 +3757,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.indexableElem(zcu); const ptr = switch (ptr_ty.ptrSize(zcu)) { @@ -3790,7 +3790,7 @@ fn airOverflow( assert(isByRef(inst_ty, zcu)); // auto structs are by-ref const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value); + const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value); const results = try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); @@ -3863,7 +3863,7 @@ fn buildFloatCmp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3969,7 +3969,7 @@ fn buildFloatOp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try o.lowerType(ty, .by_value); + const llvm_ty = try o.lowerType(ty, .as_value); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics @@ -4074,7 +4074,7 @@ fn buildFloatOp( }), }; - const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); + const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); const libc_fn = try o.getLibcFunction( fn_name, @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len], @@ -4129,7 +4129,7 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil const dest_ty = self.typeOfIndex(inst); assert(isByRef(dest_ty, zcu)); // auto structs are by-ref - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); const result = try self.wip.bin(.shl, lhs, casted_rhs, ""); const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) @@ -4196,7 +4196,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) .@"shl nsw" else @@ -4217,7 +4217,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { // features which we do not use. Therefore this branch is currently impossible. unreachable; } - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); return self.wip.bin(.shl, lhs, casted_rhs, ""); } @@ -4231,8 +4231,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const lhs_ty = self.typeOf(bin_op.lhs); const lhs_info = lhs_ty.intInfo(zcu); - const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value); - const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value); + const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value); + const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value); const rhs_ty = self.typeOf(bin_op.rhs); if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) { @@ -4242,8 +4242,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } const rhs_info = rhs_ty.intInfo(zcu); assert(rhs_info.signedness == .unsigned); - const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value); - const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value); + const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value); + const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value); const result = try self.wip.callIntrinsic( .normal, @@ -4319,7 +4319,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error! } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .by_value), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty, .as_value), ""); const is_signed_int = lhs_scalar_ty.isSignedInt(zcu); return self.wip.bin(if (is_exact) @@ -4340,7 +4340,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, .abs, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{ operand, .false }, "", ), @@ -4354,7 +4354,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! const zcu = o.zcu; const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; const dest_ty = fg.typeOfIndex(inst); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const operand = try fg.resolveInst(ty_op.operand); const operand_ty = fg.typeOf(ty_op.operand); const operand_info = operand_ty.intInfo(zcu); @@ -4382,8 +4382,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! if (!have_min_check and !have_max_check) break :bounds_check; - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector)); @@ -4461,7 +4461,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); - const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .by_value); + const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst), .as_value); return self.wip.cast(.trunc, operand, dest_llvm_ty, ""); } @@ -4475,10 +4475,10 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), ""); + return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_bits = dest_ty.floatBits(target); const src_bits = operand_ty.floatBits(target); @@ -4509,10 +4509,10 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), ""); + return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); + const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); + const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_bits = dest_ty.scalarType(zcu).floatBits(target); const src_bits = operand_ty.scalarType(zcu).floatBits(target); @@ -4563,7 +4563,7 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! assert(!isByRef(operand_ty, zcu)); assert(!isByRef(dest_ty, zcu)); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) { const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty); @@ -4606,7 +4606,7 @@ fn airPtrFromInt(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu)); const operand = try fg.resolveInst(ty_op.operand); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); } @@ -4620,7 +4620,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val assert(dest_ty.scalarType(zcu).toIntern() == .usize_type); const operand = try fg.resolveInst(ty_op.operand); - const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); + const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); } @@ -4832,7 +4832,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu return .none; } - const len = try o.builder.intValue(try o.lowerType(.usize, .by_value), elem_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize, .as_value), elem_ty.abiSize(zcu)); _ = try fg.wip.callMemSet( ptr, ptr_alignment.toLlvm(), @@ -4867,7 +4867,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu if (ptr_info.packed_offset.host_size != 0) { // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); - const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value); + const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind); @@ -4945,14 +4945,14 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); - const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .by_value); + const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal); const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset); const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, ""); - const elem_llvm_ty = try o.lowerType(elem_ty, .by_value); + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { const same_size_int = try o.builder.intType(@intCast(elem_bits)); @@ -5002,7 +5002,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const o = self.object; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); @@ -5014,7 +5014,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); - return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .by_value), ""); + return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize, .as_value), ""); } fn airCmpxchg( @@ -5031,7 +5031,7 @@ fn airCmpxchg( var expected_value = try self.resolveInst(extra.expected_value); var new_value = try self.resolveInst(extra.new_value); const operand_ty = ptr_ty.childType(zcu); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false); if (llvm_abi_ty != .none) { // operand needs widening and truncating @@ -5101,7 +5101,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const access_kind: Builder.MemoryAccessKind = if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -5130,7 +5130,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va // If we are storing a pointer we need to convert to and from a plain old integer. const non_ptr_operand = switch (operand_ty.zigTypeTag(zcu)) { - .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .by_value), ""), + .pointer => try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize, .as_value), ""), else => operand, }; @@ -5169,7 +5169,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm(); const access_kind: Builder.MemoryAccessKind = if (info.flags.is_volatile) .@"volatile" else .normal; - const elem_llvm_ty = try o.lowerType(elem_ty, .by_value); + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); self.maybeMarkAllowZeroAccess(info); @@ -5503,11 +5503,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{ operand, .false }, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { @@ -5521,11 +5521,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(operand_ty, .by_value)}, + &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5538,7 +5538,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const inst_ty = self.typeOfIndex(inst); var operand = try self.resolveInst(ty_op.operand); - var llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + var llvm_operand_ty = try o.lowerType(operand_ty, .as_value); if (bits % 16 == 8) { // If not an even byte-multiple, we need zero-extend + shift-left 1 byte @@ -5559,7 +5559,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const result = try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, ""); - return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .by_value), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty, .as_value), ""); } fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5579,7 +5579,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui for (0..names.len) |name_index| { const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?; - const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.by_value), err_int); + const this_tag_int_value = try o.builder.intConst(try o.errorIntType(.as_value), err_int); try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip); } self.wip.cursor = .{ .block = valid_block }; @@ -5638,7 +5638,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const slice_ty = self.typeOfIndex(inst); // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed. - const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .by_value), ""); + const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize, .as_value), ""); const error_name_table_ptr = try o.getErrorNameTable(); const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu)); @@ -5649,7 +5649,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const scalar = try self.resolveInst(ty_op.operand); const vector_ty = self.typeOfIndex(inst); - return self.wip.splatVector(try self.object.lowerType(vector_ty, .by_value), scalar, ""); + return self.wip.splatVector(try self.object.lowerType(vector_ty, .as_value), scalar, ""); } fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5672,9 +5672,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const operand = try fg.resolveInst(unwrapped.operand); const mask = unwrapped.mask; const operand_ty = fg.typeOf(unwrapped.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); - const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value); - const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); + const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value); const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); @@ -5704,7 +5704,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val .elem => llvm_poison_elem, .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: { any_defined_comptime_value = true; - break :elem try o.lowerValue(val, .by_value); + break :elem try o.lowerValue(val, .as_value); } else llvm_poison_elem, }; } @@ -5776,7 +5776,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); const mask = unwrapped.mask; - const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); @@ -5866,7 +5866,7 @@ fn buildReducedCall( accum_init: Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len); const llvm_result_ty = accum_init.typeOfWip(&self.wip); @@ -5924,9 +5924,9 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce; const operand = try self.resolveInst(reduce.operand); const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); + const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value); + const llvm_scalar_ty = try o.lowerType(scalar_ty, .as_value); switch (reduce.operation) { .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { @@ -6036,7 +6036,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde switch (result_ty.zigTypeTag(zcu)) { .vector => { - const llvm_result_ty = try o.lowerType(result_ty, .by_value); + const llvm_result_ty = try o.lowerType(result_ty, .as_value); var vector = try o.builder.poisonValue(llvm_result_ty); for (elements, 0..) |elem, i| { const index_u32 = try o.builder.intValue(.i32, i); @@ -6153,10 +6153,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const loaded_enum = ip.loadEnumType(tag_ty.toIntern()); const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) { .none => try o.builder.intConst( - try o.lowerType(.fromInterned(union_obj.enum_tag_type), .by_value), + try o.lowerType(.fromInterned(union_obj.enum_tag_type), .as_value), extra.field_index, // auto-numbered ), - else => |tag_val_ip| try o.lowerValue(tag_val_ip, .by_value), + else => |tag_val_ip| try o.lowerValue(tag_val_ip, .as_value), }; const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset()); try self.store(tag_ptr, layout.tag_align, llvm_tag_val.toValue(), tag_ty, .normal); @@ -6218,7 +6218,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .by_value), ""); + return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty, .as_value), ""); } fn workIntrinsic( @@ -6370,7 +6370,7 @@ fn load( }; if (isByRef(load_ty, zcu)) { - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const result_ptr = try fg.buildZigAlloca(load_ty, .none); _ = try fg.wip.callMemCpy( result_ptr, @@ -6385,7 +6385,7 @@ fn load( } const llvm_memory_ty = try o.lowerType(load_ty, .in_memory); - const llvm_value_ty = try o.lowerType(load_ty, .by_value); + const llvm_value_ty = try o.lowerType(load_ty, .as_value); if (llvm_memory_ty != llvm_value_ty) { assert(load_ty.isAbiInt(zcu)); @@ -6443,7 +6443,7 @@ fn store( }; if (isByRef(elem_ty, zcu)) { - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); _ = try fg.wip.callMemCpy( ptr, llvm_ptr_align, @@ -6456,10 +6456,10 @@ fn store( return; } - assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .by_value)); + assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value)); const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory); - const llvm_value_ty = try o.lowerType(elem_ty, .by_value); + const llvm_value_ty = try o.lowerType(elem_ty, .as_value); if (llvm_memory_ty != llvm_value_ty) { assert(elem_ty.isAbiInt(zcu)); @@ -6494,7 +6494,7 @@ fn store( fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; const o = fg.object; - const usize_ty = try o.lowerType(.usize, .by_value); + const usize_ty = try o.lowerType(.usize, .as_value); const zero = try o.builder.intValue(usize_ty, 0); const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, ""); @@ -6516,7 +6516,7 @@ fn valgrindClientRequest( const target = zcu.getTarget(); if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; - const llvm_usize = try o.lowerType(.usize, .by_value); + const llvm_usize = try o.lowerType(.usize, .as_value); const usize_align = Type.usize.abiAlignment(zcu).toLlvm(); const array_llvm_ty = try o.builder.arrayType(6, llvm_usize); @@ -6798,7 +6798,7 @@ const ParamTypeIterator = struct { while (field_it.next()) |field_index| { const field_ty = ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .by_value); + it.types_buffer[it.types_len] = try it.object.lowerType(field_ty, .as_value); it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu); it.types_len += 1; } @@ -6815,7 +6815,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; return .byval; } else { - it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .by_value)}; + it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)}; it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; it.types_len = 1; it.llvm_index += 1; @@ -7080,7 +7080,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err for (0..ret_ty.structFieldCount(zcu)) |field_index| { const field_ty = ret_ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - types[types_len] = try o.lowerType(field_ty, .by_value); + types[types_len] = try o.lowerType(field_ty, .as_value); types_len += 1; } return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; @@ -7091,7 +7091,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err assert(!isByRef(ret_ty, zcu)); return .by_val; } else { - return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) }; + return .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }; }, .indirect => return .sret, }, @@ -7392,7 +7392,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { if (offset == 0) return ptr; const o = fg.object; - const llvm_usize_ty = try o.lowerType(.usize, .by_value); + const llvm_usize_ty = try o.lowerType(.usize, .as_value); const offset_val = try o.builder.intValue(llvm_usize_ty, offset); return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); } -- 2.54.0 From 1e4b0e0022fcbda51032fe555d948ae59db3f640 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 00:39:25 -0400 Subject: [PATCH 047/215] llvm: update attributes and intrinsics --- lib/std/zig/llvm/Builder.zig | 1211 +++++++++++++++++++++------------- 1 file changed, 758 insertions(+), 453 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index d0e86c80ac3baa8c9504095b8200b546789a39b2..48ae8216b9026099894b01f95ca9505215bef869 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -142,8 +142,8 @@ pub const String = enum(u32) { } fn fromIndex(index: ?usize) String { - return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + - @backingInt(String.empty))))); + return @fromBackingInt(@as(u32, @intCast((index orelse return .none) + + @backingInt(String.empty)))); } fn toIndex(self: String) ?usize { @@ -937,6 +937,7 @@ pub const Attribute = union(Kind) { // Parameter Attributes zeroext, signext, + noext, inreg, byval: Type, byref: Type, @@ -947,6 +948,7 @@ pub const Attribute = union(Kind) { @"align": Alignment.Lazy, @"noalias", nocapture, + captures: Captures, nofree, nest, returned, @@ -965,6 +967,11 @@ pub const Attribute = union(Kind) { readnone, readonly, writeonly, + writable, + initializes: []const [2]u64, + dead_on_unwind, + dead_on_return: ?u32, + range: [2]Constant, // Function Attributes //alignstack: Alignment.Lazy, @@ -974,7 +981,7 @@ pub const Attribute = union(Kind) { builtin, cold, convergent, - disable_sanitizer_information, + disable_sanitizer_instrumentation, fn_ret_thunk_extern, hot, inlinehint, @@ -984,6 +991,7 @@ pub const Attribute = union(Kind) { naked, nobuiltin, nocallback, + nodivergencesource, noduplicate, //nofree, noimplicitfloat, @@ -1001,6 +1009,7 @@ pub const Attribute = union(Kind) { nosanitize_bounds, nosanitize_coverage, null_pointer_is_valid, + optdebug, optforfuzzing, optnone, optsize, @@ -1012,23 +1021,23 @@ pub const Attribute = union(Kind) { sanitize_thread, sanitize_hwaddress, sanitize_memtag, + sanitize_realtime, + sanitize_realtime_blocking, + sanitize_alloc_token, speculative_load_hardening, speculatable, ssp, sspstrong, sspreq, strictfp, + denormal_fpenv, uwtable: UwTable, nocf_check, shadowcallstack, mustprogress, vscale_range: VScaleRange, - - // Global Attributes - no_sanitize_address, - no_sanitize_hwaddress, - //sanitize_memtag, - sanitize_address_dyninit, + nooutline, + nocreateundeforpoison, string: struct { kind: String, value: String }, none: noreturn, @@ -1045,100 +1054,11 @@ pub const Attribute = union(Kind) { const storage = self.toStorage(builder); if (storage.kind.toString()) |kind| return .{ .string = .{ .kind = kind, - .value = @fromBackingInt(@intCast(storage.value)), + .value = @fromBackingInt(storage.value), } } else return switch (storage.kind) { - inline .zeroext, - .signext, - .inreg, - .byval, - .byref, - .preallocated, - .inalloca, - .sret, - .elementtype, - .@"align", - .@"noalias", - .nocapture, - .nofree, - .nest, - .returned, - .nonnull, - .dereferenceable, - .dereferenceable_or_null, - .swiftself, - .swiftasync, - .swifterror, - .immarg, - .noundef, - .nofpclass, - .alignstack, - .allocalign, - .allocptr, - .readnone, - .readonly, - .writeonly, - //.alignstack, - .allockind, - .allocsize, - .alwaysinline, - .builtin, - .cold, - .convergent, - .disable_sanitizer_information, - .fn_ret_thunk_extern, - .hot, - .inlinehint, - .jumptable, - .memory, - .minsize, - .naked, - .nobuiltin, - .nocallback, - .noduplicate, - //.nofree, - .noimplicitfloat, - .@"noinline", - .nomerge, - .nonlazybind, - .noprofile, - .skipprofile, - .noredzone, - .noreturn, - .norecurse, - .willreturn, - .nosync, - .nounwind, - .nosanitize_bounds, - .nosanitize_coverage, - .null_pointer_is_valid, - .optforfuzzing, - .optnone, - .optsize, - //.preallocated, - .returns_twice, - .safestack, - .sanitize_address, - .sanitize_memory, - .sanitize_thread, - .sanitize_hwaddress, - .sanitize_memtag, - .speculative_load_hardening, - .speculatable, - .ssp, - .sspstrong, - .sspreq, - .strictfp, - .uwtable, - .nocf_check, - .shadowcallstack, - .mustprogress, - .vscale_range, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, - => |kind| { + inline else => |kind| { const field_name, const field_type = comptime blk: { - @setEvalBranchQuota(10_000); + @setEvalBranchQuota(12_000); const info = @typeInfo(Attribute).@"union"; for (info.field_names, info.field_types) |field_name, field_type| { if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type }; @@ -1149,14 +1069,17 @@ pub const Attribute = union(Kind) { return @unionInit(Attribute, field_name, switch (field_type) { void => {}, u32 => storage.value, - Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)), - AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), + Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value), + AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value), else => @compileError("bad payload type: " ++ field_name ++ ": " ++ @typeName(field_type)), }); }, - .string, .none => unreachable, - _ => unreachable, + .initializes, + .dead_on_return, + .range, + => @panic("TODO"), + .string, .none, _ => unreachable, }; } @@ -1174,6 +1097,7 @@ pub const Attribute = union(Kind) { switch (attribute) { .zeroext, .signext, + .noext, .inreg, .@"noalias", .nocapture, @@ -1191,11 +1115,13 @@ pub const Attribute = union(Kind) { .readnone, .readonly, .writeonly, + .writable, + .dead_on_unwind, .alwaysinline, .builtin, .cold, .convergent, - .disable_sanitizer_information, + .disable_sanitizer_instrumentation, .fn_ret_thunk_extern, .hot, .inlinehint, @@ -1204,6 +1130,7 @@ pub const Attribute = union(Kind) { .naked, .nobuiltin, .nocallback, + .nodivergencesource, .noduplicate, .noimplicitfloat, .@"noinline", @@ -1220,6 +1147,7 @@ pub const Attribute = union(Kind) { .nosanitize_bounds, .nosanitize_coverage, .null_pointer_is_valid, + .optdebug, .optforfuzzing, .optnone, .optsize, @@ -1230,18 +1158,21 @@ pub const Attribute = union(Kind) { .sanitize_thread, .sanitize_hwaddress, .sanitize_memtag, + .sanitize_realtime, + .sanitize_realtime_blocking, + .sanitize_alloc_token, .speculative_load_hardening, .speculatable, .ssp, .sspstrong, .sspreq, .strictfp, + .denormal_fpenv, .nocf_check, .shadowcallstack, .mustprogress, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, + .nooutline, + .nocreateundeforpoison, => try w.print(" {s}", .{@tagName(attribute)}), .byval, .byref, @@ -1254,6 +1185,45 @@ pub const Attribute = union(Kind) { .dereferenceable, .dereferenceable_or_null, => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), + .captures => |captures| { + try w.print(" {s}(", .{@tagName(attribute)}); + var need_comma = false; + if (captures == Captures.none) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("none"); + need_comma = true; + } + inline for (@typeInfo(Captures).@"struct".field_names) |field_name| { + if (comptime std.mem.eql(u8, field_name, "_")) continue; + const components = @field(captures, field_name); + if (components != Captures.Components.none) { + if (!comptime std.mem.eql(u8, field_name, "other")) { + if (need_comma) try w.writeAll(", "); + try w.writeAll(field_name ++ ": "); + need_comma = false; + } + if (components.address) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("address"); + need_comma = true; + } else if (components.address_is_null) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("address_is_null"); + need_comma = true; + } + if (components.provenance) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("provenance"); + need_comma = true; + } else if (components.read_provenance) { + if (need_comma) try w.writeAll(", "); + try w.writeAll("read_provenance"); + need_comma = true; + } + } + } + try w.writeByte(')'); + }, .nofpclass => |fpclass| { const Int = @typeInfo(FpClass).@"struct".backing_integer.?; try w.print(" {s}(", .{@tagName(attribute)}); @@ -1281,6 +1251,9 @@ pub const Attribute = union(Kind) { try w.print("({d})", .{alignment_bytes}); } }, + .initializes => @panic("TODO"), + .dead_on_return => @panic("TODO"), + .range => @panic("TODO"), .allockind => |allockind| { try w.print(" {t}(\"", .{attribute}); var any = false; @@ -1344,100 +1317,109 @@ pub const Attribute = union(Kind) { pub const Kind = enum(u32) { // Parameter Attributes - zeroext = 34, - signext = 24, - inreg = 5, - byval = 3, - byref = 69, - preallocated = 65, - inalloca = 38, - sret = 29, // TODO: ? - elementtype = 77, - @"align" = 1, - @"noalias" = 9, - nocapture = 11, - nofree = 62, - nest = 8, - returned = 22, - nonnull = 39, - dereferenceable = 41, - dereferenceable_or_null = 42, - swiftself = 46, - swiftasync = 75, - swifterror = 47, - immarg = 60, - noundef = 68, - nofpclass = 87, - alignstack = 25, - allocalign = 80, - allocptr = 81, - readnone = 20, - readonly = 21, - writeonly = 52, + zeroext = @backingInt(ATTR_KIND.Z_EXT), + signext = @backingInt(ATTR_KIND.S_EXT), + noext = @backingInt(ATTR_KIND.NO_EXT), + inreg = @backingInt(ATTR_KIND.IN_REG), + byval = @backingInt(ATTR_KIND.BY_VAL), + byref = @backingInt(ATTR_KIND.BYREF), + preallocated = @backingInt(ATTR_KIND.PREALLOCATED), + inalloca = @backingInt(ATTR_KIND.IN_ALLOCA), + sret = @backingInt(ATTR_KIND.STRUCT_RET), + elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE), + @"align" = @backingInt(ATTR_KIND.ALIGNMENT), + @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS), + nocapture = @backingInt(ATTR_KIND.NO_CAPTURE), + captures = @backingInt(ATTR_KIND.CAPTURES), + nofree = @backingInt(ATTR_KIND.NOFREE), + nest = @backingInt(ATTR_KIND.NEST), + returned = @backingInt(ATTR_KIND.RETURNED), + nonnull = @backingInt(ATTR_KIND.NON_NULL), + dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE), + dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL), + swiftself = @backingInt(ATTR_KIND.SWIFT_SELF), + swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC), + swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR), + immarg = @backingInt(ATTR_KIND.IMMARG), + noundef = @backingInt(ATTR_KIND.NOUNDEF), + nofpclass = @backingInt(ATTR_KIND.NOFPCLASS), + alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT), + allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN), + allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER), + readnone = @backingInt(ATTR_KIND.READ_NONE), + readonly = @backingInt(ATTR_KIND.READ_ONLY), + writeonly = @backingInt(ATTR_KIND.WRITEONLY), + writable = @backingInt(ATTR_KIND.WRITABLE), + initializes = @backingInt(ATTR_KIND.INITIALIZES), + dead_on_unwind = @backingInt(ATTR_KIND.DEAD_ON_UNWIND), + dead_on_return = @backingInt(ATTR_KIND.DEAD_ON_RETURN), + range = @backingInt(ATTR_KIND.RANGE), // Function Attributes - //alignstack, - allockind = 82, - allocsize = 51, - alwaysinline = 2, - builtin = 35, - cold = 36, - convergent = 43, - disable_sanitizer_information = 78, - fn_ret_thunk_extern = 84, - hot = 72, - inlinehint = 4, - jumptable = 40, - memory = 86, - minsize = 6, - naked = 7, - nobuiltin = 10, - nocallback = 71, - noduplicate = 12, - //nofree, - noimplicitfloat = 13, - @"noinline" = 14, - nomerge = 66, - nonlazybind = 15, - noprofile = 73, - skipprofile = 85, - noredzone = 16, - noreturn = 17, - norecurse = 48, - willreturn = 61, - nosync = 63, - nounwind = 18, - nosanitize_bounds = 79, - nosanitize_coverage = 76, - null_pointer_is_valid = 67, - optforfuzzing = 57, - optnone = 37, - optsize = 19, - //preallocated, - returns_twice = 23, - safestack = 44, - sanitize_address = 30, - sanitize_memory = 32, - sanitize_thread = 31, - sanitize_hwaddress = 55, - sanitize_memtag = 64, - speculative_load_hardening = 59, - speculatable = 53, - ssp = 26, - sspstrong = 28, - sspreq = 27, - strictfp = 54, - uwtable = 33, - nocf_check = 56, - shadowcallstack = 58, - mustprogress = 70, - vscale_range = 74, - - // Global Attributes - no_sanitize_address = 100, - no_sanitize_hwaddress = 101, - //sanitize_memtag, - sanitize_address_dyninit = 102, + //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT), + allockind = @backingInt(ATTR_KIND.ALLOC_KIND), + allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE), + alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE), + builtin = @backingInt(ATTR_KIND.BUILTIN), + cold = @backingInt(ATTR_KIND.COLD), + convergent = @backingInt(ATTR_KIND.CONVERGENT), + disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION), + fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN), + hot = @backingInt(ATTR_KIND.HOT), + inlinehint = @backingInt(ATTR_KIND.INLINE_HINT), + jumptable = @backingInt(ATTR_KIND.JUMP_TABLE), + memory = @backingInt(ATTR_KIND.MEMORY), + minsize = @backingInt(ATTR_KIND.MIN_SIZE), + naked = @backingInt(ATTR_KIND.NAKED), + nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN), + nocallback = @backingInt(ATTR_KIND.NO_CALLBACK), + nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE), + noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE), + //nofree = @intFromEnum(ATTR_KIND.NOFREE), + noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT), + @"noinline" = @backingInt(ATTR_KIND.NO_INLINE), + nomerge = @backingInt(ATTR_KIND.NO_MERGE), + nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND), + noprofile = @backingInt(ATTR_KIND.NO_PROFILE), + skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE), + noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE), + noreturn = @backingInt(ATTR_KIND.NO_RETURN), + norecurse = @backingInt(ATTR_KIND.NO_RECURSE), + willreturn = @backingInt(ATTR_KIND.WILLRETURN), + nosync = @backingInt(ATTR_KIND.NOSYNC), + nounwind = @backingInt(ATTR_KIND.NO_UNWIND), + nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS), + nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE), + null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID), + optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING), + optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING), + optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE), + optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE), + //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED), + returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE), + safestack = @backingInt(ATTR_KIND.SAFESTACK), + sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS), + sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY), + sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD), + sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS), + sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG), + sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME), + sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING), + sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN), + speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING), + speculatable = @backingInt(ATTR_KIND.SPECULATABLE), + ssp = @backingInt(ATTR_KIND.STACK_PROTECT), + sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG), + sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ), + strictfp = @backingInt(ATTR_KIND.STRICT_FP), + denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV), + uwtable = @backingInt(ATTR_KIND.UW_TABLE), + nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK), + shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK), + mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS), + vscale_range = @backingInt(ATTR_KIND.VSCALE_RANGE), + nooutline = @backingInt(ATTR_KIND.NOOUTLINE), + nocreateundeforpoison = @backingInt(ATTR_KIND.NO_CREATE_UNDEF_OR_POISON), string = maxInt(u31), none = maxInt(u32), @@ -1447,16 +1429,128 @@ pub const Attribute = union(Kind) { pub fn fromString(str: String) Kind { assert(!str.isAnon()); - const kind: Kind = @fromBackingInt(@intCast(@backingInt(str))); + const kind: Kind = @fromBackingInt(@backingInt(str)); assert(kind != .none); return kind; } fn toString(self: Kind) ?String { assert(self != .none); - const str: String = @fromBackingInt(@intCast(@backingInt(self))); + const str: String = @fromBackingInt(@backingInt(self)); return if (str.isAnon()) null else str; } + + /// enum AttributeKindCodes + const ATTR_KIND = enum(u32) { + ALIGNMENT = 1, + ALWAYS_INLINE = 2, + BY_VAL = 3, + INLINE_HINT = 4, + IN_REG = 5, + MIN_SIZE = 6, + NAKED = 7, + NEST = 8, + NO_ALIAS = 9, + NO_BUILTIN = 10, + NO_CAPTURE = 11, + NO_DUPLICATE = 12, + NO_IMPLICIT_FLOAT = 13, + NO_INLINE = 14, + NON_LAZY_BIND = 15, + NO_RED_ZONE = 16, + NO_RETURN = 17, + NO_UNWIND = 18, + OPTIMIZE_FOR_SIZE = 19, + READ_NONE = 20, + READ_ONLY = 21, + RETURNED = 22, + RETURNS_TWICE = 23, + S_EXT = 24, + STACK_ALIGNMENT = 25, + STACK_PROTECT = 26, + STACK_PROTECT_REQ = 27, + STACK_PROTECT_STRONG = 28, + STRUCT_RET = 29, + SANITIZE_ADDRESS = 30, + SANITIZE_THREAD = 31, + SANITIZE_MEMORY = 32, + UW_TABLE = 33, + Z_EXT = 34, + BUILTIN = 35, + COLD = 36, + OPTIMIZE_NONE = 37, + IN_ALLOCA = 38, + NON_NULL = 39, + JUMP_TABLE = 40, + DEREFERENCEABLE = 41, + DEREFERENCEABLE_OR_NULL = 42, + CONVERGENT = 43, + SAFESTACK = 44, + ARGMEMONLY = 45, + SWIFT_SELF = 46, + SWIFT_ERROR = 47, + NO_RECURSE = 48, + INACCESSIBLEMEM_ONLY = 49, + INACCESSIBLEMEM_OR_ARGMEMONLY = 50, + ALLOC_SIZE = 51, + WRITEONLY = 52, + SPECULATABLE = 53, + STRICT_FP = 54, + SANITIZE_HWADDRESS = 55, + NOCF_CHECK = 56, + OPT_FOR_FUZZING = 57, + SHADOWCALLSTACK = 58, + SPECULATIVE_LOAD_HARDENING = 59, + IMMARG = 60, + WILLRETURN = 61, + NOFREE = 62, + NOSYNC = 63, + SANITIZE_MEMTAG = 64, + PREALLOCATED = 65, + NO_MERGE = 66, + NULL_POINTER_IS_VALID = 67, + NOUNDEF = 68, + BYREF = 69, + MUSTPROGRESS = 70, + NO_CALLBACK = 71, + HOT = 72, + NO_PROFILE = 73, + VSCALE_RANGE = 74, + SWIFT_ASYNC = 75, + NO_SANITIZE_COVERAGE = 76, + ELEMENTTYPE = 77, + DISABLE_SANITIZER_INSTRUMENTATION = 78, + NO_SANITIZE_BOUNDS = 79, + ALLOC_ALIGN = 80, + ALLOCATED_POINTER = 81, + ALLOC_KIND = 82, + PRESPLIT_COROUTINE = 83, + FNRETTHUNK_EXTERN = 84, + SKIP_PROFILE = 85, + MEMORY = 86, + NOFPCLASS = 87, + OPTIMIZE_FOR_DEBUGGING = 88, + WRITABLE = 89, + CORO_ONLY_DESTROY_WHEN_COMPLETE = 90, + DEAD_ON_UNWIND = 91, + RANGE = 92, + SANITIZE_NUMERICAL_STABILITY = 93, + INITIALIZES = 94, + HYBRID_PATCHABLE = 95, + SANITIZE_REALTIME = 96, + SANITIZE_REALTIME_BLOCKING = 97, + CORO_ELIDE_SAFE = 98, + NO_EXT = 99, + NO_DIVERGENCE_SOURCE = 100, + SANITIZE_TYPE = 101, + CAPTURES = 102, + DEAD_ON_RETURN = 103, + SANITIZE_ALLOC_TOKEN = 104, + NO_CREATE_UNDEF_OR_POISON = 105, + DENORMAL_FPENV = 106, + NOOUTLINE = 107, + FLATTEN = 108, + }; }; pub const FpClass = packed struct(u32) { @@ -1506,6 +1600,29 @@ pub const Attribute = union(Kind) { pub const pnorm = FpClass{ .positive_normal = true }; }; + pub const Captures = packed struct(u32) { + other: Components = .none, + ret: Components = .none, + _: u24 = 0, + + pub const none: Captures = .{}; + + pub const Components = packed struct(u4) { + address_is_null: bool = false, + address: bool = false, + read_provenance: bool = false, + provenance: bool = false, + + pub const none: Components = .{}; + pub const all: Components = .{ + .address_is_null = true, + .address = true, + .read_provenance = true, + .provenance = true, + }; + }; + }; + pub const AllocKind = packed struct(u32) { alloc: bool, realloc: bool, @@ -1582,9 +1699,13 @@ pub const Attribute = union(Kind) { void => 0, u32 => value, Alignment.Lazy, String, Type, UwTable => @backingInt(value), - AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), - else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), + AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value), + else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))), } }, + .initializes, + .dead_on_return, + .range, + => @panic("TODO"), .string => |string_attr| .{ .kind = Kind.fromString(string_attr.kind), .value = @backingInt(string_attr.value), @@ -1907,87 +2028,87 @@ pub const AddrSpace = enum(u24) { // See llvm/lib/Target/X86/X86.h pub const x86 = struct { - pub const gs: AddrSpace = @fromBackingInt(@intCast(256)); - pub const fs: AddrSpace = @fromBackingInt(@intCast(257)); - pub const ss: AddrSpace = @fromBackingInt(@intCast(258)); + pub const gs: AddrSpace = @fromBackingInt(256); + pub const fs: AddrSpace = @fromBackingInt(257); + pub const ss: AddrSpace = @fromBackingInt(258); - pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270)); - pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271)); - pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272)); + pub const ptr32_sptr: AddrSpace = @fromBackingInt(270); + pub const ptr32_uptr: AddrSpace = @fromBackingInt(271); + pub const ptr64: AddrSpace = @fromBackingInt(272); }; pub const x86_64 = x86; // See llvm/lib/Target/AVR/AVR.h pub const avr = struct { - pub const data: AddrSpace = @fromBackingInt(@intCast(0)); - pub const program: AddrSpace = @fromBackingInt(@intCast(1)); - pub const program1: AddrSpace = @fromBackingInt(@intCast(2)); - pub const program2: AddrSpace = @fromBackingInt(@intCast(3)); - pub const program3: AddrSpace = @fromBackingInt(@intCast(4)); - pub const program4: AddrSpace = @fromBackingInt(@intCast(5)); - pub const program5: AddrSpace = @fromBackingInt(@intCast(6)); + pub const data: AddrSpace = @fromBackingInt(0); + pub const program: AddrSpace = @fromBackingInt(1); + pub const program1: AddrSpace = @fromBackingInt(2); + pub const program2: AddrSpace = @fromBackingInt(3); + pub const program3: AddrSpace = @fromBackingInt(4); + pub const program4: AddrSpace = @fromBackingInt(5); + pub const program5: AddrSpace = @fromBackingInt(6); }; // See llvm/lib/Target/NVPTX/NVPTX.h pub const nvptx = struct { - pub const generic: AddrSpace = @fromBackingInt(@intCast(0)); - pub const global: AddrSpace = @fromBackingInt(@intCast(1)); - pub const constant: AddrSpace = @fromBackingInt(@intCast(2)); - pub const shared: AddrSpace = @fromBackingInt(@intCast(3)); - pub const param: AddrSpace = @fromBackingInt(@intCast(4)); - pub const local: AddrSpace = @fromBackingInt(@intCast(5)); + pub const generic: AddrSpace = @fromBackingInt(0); + pub const global: AddrSpace = @fromBackingInt(1); + pub const constant: AddrSpace = @fromBackingInt(2); + pub const shared: AddrSpace = @fromBackingInt(3); + pub const param: AddrSpace = @fromBackingInt(4); + pub const local: AddrSpace = @fromBackingInt(5); }; // See llvm/lib/Target/AMDGPU/AMDGPU.h pub const amdgpu = struct { - pub const flat: AddrSpace = @fromBackingInt(@intCast(0)); - pub const global: AddrSpace = @fromBackingInt(@intCast(1)); - pub const region: AddrSpace = @fromBackingInt(@intCast(2)); - pub const local: AddrSpace = @fromBackingInt(@intCast(3)); - pub const constant: AddrSpace = @fromBackingInt(@intCast(4)); - pub const private: AddrSpace = @fromBackingInt(@intCast(5)); - pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6)); - pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7)); - pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8)); - pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9)); - pub const param_d: AddrSpace = @fromBackingInt(@intCast(6)); - pub const param_i: AddrSpace = @fromBackingInt(@intCast(7)); - pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8)); - pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9)); - pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10)); - pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11)); - pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12)); - pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13)); - pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14)); - pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15)); - pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16)); - pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17)); - pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18)); - pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19)); - pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20)); - pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21)); - pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22)); - pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23)); - pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128)); + pub const flat: AddrSpace = @fromBackingInt(0); + pub const global: AddrSpace = @fromBackingInt(1); + pub const region: AddrSpace = @fromBackingInt(2); + pub const local: AddrSpace = @fromBackingInt(3); + pub const constant: AddrSpace = @fromBackingInt(4); + pub const private: AddrSpace = @fromBackingInt(5); + pub const constant_32bit: AddrSpace = @fromBackingInt(6); + pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7); + pub const buffer_resource: AddrSpace = @fromBackingInt(8); + pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9); + pub const param_d: AddrSpace = @fromBackingInt(6); + pub const param_i: AddrSpace = @fromBackingInt(7); + pub const constant_buffer_0: AddrSpace = @fromBackingInt(8); + pub const constant_buffer_1: AddrSpace = @fromBackingInt(9); + pub const constant_buffer_2: AddrSpace = @fromBackingInt(10); + pub const constant_buffer_3: AddrSpace = @fromBackingInt(11); + pub const constant_buffer_4: AddrSpace = @fromBackingInt(12); + pub const constant_buffer_5: AddrSpace = @fromBackingInt(13); + pub const constant_buffer_6: AddrSpace = @fromBackingInt(14); + pub const constant_buffer_7: AddrSpace = @fromBackingInt(15); + pub const constant_buffer_8: AddrSpace = @fromBackingInt(16); + pub const constant_buffer_9: AddrSpace = @fromBackingInt(17); + pub const constant_buffer_10: AddrSpace = @fromBackingInt(18); + pub const constant_buffer_11: AddrSpace = @fromBackingInt(19); + pub const constant_buffer_12: AddrSpace = @fromBackingInt(20); + pub const constant_buffer_13: AddrSpace = @fromBackingInt(21); + pub const constant_buffer_14: AddrSpace = @fromBackingInt(22); + pub const constant_buffer_15: AddrSpace = @fromBackingInt(23); + pub const streamout_register: AddrSpace = @fromBackingInt(128); }; pub const spirv = struct { - pub const function: AddrSpace = @fromBackingInt(@intCast(0)); - pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1)); - pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2)); - pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3)); - pub const generic: AddrSpace = @fromBackingInt(@intCast(4)); - pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5)); - pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6)); - pub const input: AddrSpace = @fromBackingInt(@intCast(7)); + pub const function: AddrSpace = @fromBackingInt(0); + pub const cross_workgroup: AddrSpace = @fromBackingInt(1); + pub const uniform_constant: AddrSpace = @fromBackingInt(2); + pub const workgroup: AddrSpace = @fromBackingInt(3); + pub const generic: AddrSpace = @fromBackingInt(4); + pub const device_only_intel: AddrSpace = @fromBackingInt(5); + pub const host_only_intel: AddrSpace = @fromBackingInt(6); + pub const input: AddrSpace = @fromBackingInt(7); }; // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h pub const wasm = struct { - pub const default: AddrSpace = @fromBackingInt(@intCast(0)); - pub const variable: AddrSpace = @fromBackingInt(@intCast(1)); - pub const externref: AddrSpace = @fromBackingInt(@intCast(10)); - pub const funcref: AddrSpace = @fromBackingInt(@intCast(20)); + pub const default: AddrSpace = @fromBackingInt(0); + pub const variable: AddrSpace = @fromBackingInt(1); + pub const externref: AddrSpace = @fromBackingInt(10); + pub const funcref: AddrSpace = @fromBackingInt(20); }; pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void { @@ -2030,7 +2151,7 @@ pub const Alignment = enum(u6) { _, pub fn wrap(a: Alignment) Lazy { - return @fromBackingInt(@intCast(@backingInt(a))); + return @fromBackingInt(@backingInt(a)); } pub fn resolve(l: Lazy, b: *const Builder) Alignment { return switch (@backingInt(l)) { @@ -2261,8 +2382,7 @@ pub const StrtabString = enum(u32) { } fn fromIndex(index: ?usize) StrtabString { - return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + - @backingInt(StrtabString.empty))))); + return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty))); } fn toIndex(self: StrtabString) ?usize { @@ -2398,7 +2518,7 @@ pub const Global = struct { } pub fn toConst(global: Index) Constant { - return @fromBackingInt(@intCast(@backingInt(Constant.first_global) + @backingInt(global))); + return @fromBackingInt(@backingInt(Constant.first_global) + @backingInt(global)); } pub fn toValue(global: Index) Value { @@ -2526,7 +2646,7 @@ pub const Global = struct { _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); builder.globals.swapRemoveAt(index); if (!old_name.isAnon()) return; - builder.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(builder.next_unnamed_global) - 1)); + builder.next_unnamed_global = @fromBackingInt(@backingInt(builder.next_unnamed_global) - 1); if (builder.next_unnamed_global == old_name) return; builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder); } @@ -2539,7 +2659,7 @@ pub const Global = struct { fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { if (self.eql(other, builder)) return; - builder.next_replaced_global = @fromBackingInt(@intCast(@backingInt(builder.next_replaced_global) - 1)); + builder.next_replaced_global = @fromBackingInt(@backingInt(builder.next_replaced_global) - 1); self.renameAssumeCapacity(builder.next_replaced_global, builder); self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; } @@ -2699,6 +2819,8 @@ pub const Intrinsic = enum { smin, umax, umin, + scmp, + ucmp, memcpy, @"memcpy.inline", memmove, @@ -2708,10 +2830,21 @@ pub const Intrinsic = enum { powi, sin, cos, + tan, + asin, + acos, + atan, + atan2, + sinh, + cosh, + tanh, + sincos, + sincospi, + modf, pow, exp, - exp10, exp2, + exp10, ldexp, frexp, log, @@ -2723,6 +2856,8 @@ pub const Intrinsic = enum { maxnum, minimum, maximum, + minimumnum, + maximumnum, copysign, floor, ceil, @@ -2744,6 +2879,7 @@ pub const Intrinsic = enum { cttz, fshl, fshr, + clmul, // Arithmetic with Overflow @"sadd.with.overflow", @@ -2904,21 +3040,21 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .ptr } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .addressofreturnaddress = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .sponentry = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .frameaddress = .{ .ret_len = 1, @@ -2926,7 +3062,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .prefetch = .{ .ret_len = 0, @@ -2936,14 +3072,14 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.readwrite) } }, }, .@"thread.pointer" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .ptr } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .abs = .{ @@ -2953,7 +3089,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .smax = .{ .ret_len = 1, @@ -2962,7 +3098,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .smin = .{ .ret_len = 1, @@ -2971,7 +3107,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .umax = .{ .ret_len = 1, @@ -2980,7 +3116,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .umin = .{ .ret_len = 1, @@ -2989,7 +3125,25 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .scmp = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .ucmp = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .memcpy = .{ .ret_len = 0, @@ -3047,7 +3201,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .powi = .{ .ret_len = 1, @@ -3056,7 +3210,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .sin = .{ .ret_len = 1, @@ -3064,7 +3218,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .cos = .{ .ret_len = 1, @@ -3072,7 +3226,99 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .tan = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .asin = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .acos = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .atan = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .atan2 = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sinh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .cosh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .tanh = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sincos = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .sincospi = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .modf = .{ + .ret_len = 2, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .pow = .{ .ret_len = 1, @@ -3081,7 +3327,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp = .{ .ret_len = 1, @@ -3089,7 +3335,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp2 = .{ .ret_len = 1, @@ -3097,7 +3343,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .exp10 = .{ .ret_len = 1, @@ -3105,7 +3351,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ldexp = .{ .ret_len = 1, @@ -3114,7 +3360,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .frexp = .{ .ret_len = 2, @@ -3123,7 +3369,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log = .{ .ret_len = 1, @@ -3131,7 +3377,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log10 = .{ .ret_len = 1, @@ -3139,7 +3385,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .log2 = .{ .ret_len = 1, @@ -3147,7 +3393,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fma = .{ .ret_len = 1, @@ -3157,7 +3403,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fabs = .{ .ret_len = 1, @@ -3165,7 +3411,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .minnum = .{ .ret_len = 1, @@ -3174,7 +3420,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .maxnum = .{ .ret_len = 1, @@ -3183,7 +3429,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .minimum = .{ .ret_len = 1, @@ -3192,7 +3438,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .maximum = .{ .ret_len = 1, @@ -3201,7 +3447,25 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .minimumnum = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .maximumnum = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .copysign = .{ .ret_len = 1, @@ -3210,7 +3474,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .floor = .{ .ret_len = 1, @@ -3218,7 +3482,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ceil = .{ .ret_len = 1, @@ -3226,7 +3490,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .trunc = .{ .ret_len = 1, @@ -3234,7 +3498,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .rint = .{ .ret_len = 1, @@ -3242,7 +3506,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .nearbyint = .{ .ret_len = 1, @@ -3250,7 +3514,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .round = .{ .ret_len = 1, @@ -3258,7 +3522,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .roundeven = .{ .ret_len = 1, @@ -3266,7 +3530,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .lround = .{ .ret_len = 1, @@ -3274,7 +3538,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .llround = .{ .ret_len = 1, @@ -3282,7 +3546,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .lrint = .{ .ret_len = 1, @@ -3290,7 +3554,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .llrint = .{ .ret_len = 1, @@ -3298,7 +3562,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .bitreverse = .{ @@ -3307,7 +3571,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .bswap = .{ .ret_len = 1, @@ -3315,7 +3579,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ctpop = .{ .ret_len = 1, @@ -3323,7 +3587,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .ctlz = .{ .ret_len = 1, @@ -3332,7 +3596,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .cttz = .{ .ret_len = 1, @@ -3341,7 +3605,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fshl = .{ .ret_len = 1, @@ -3351,7 +3615,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fshr = .{ .ret_len = 1, @@ -3361,7 +3625,16 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, + }, + .clmul = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sadd.with.overflow" = .{ @@ -3372,7 +3645,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"uadd.with.overflow" = .{ .ret_len = 2, @@ -3382,7 +3655,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ssub.with.overflow" = .{ .ret_len = 2, @@ -3392,7 +3665,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"usub.with.overflow" = .{ .ret_len = 2, @@ -3402,7 +3675,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.with.overflow" = .{ .ret_len = 2, @@ -3412,7 +3685,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.with.overflow" = .{ .ret_len = 2, @@ -3422,7 +3695,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sadd.sat" = .{ @@ -3432,7 +3705,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"uadd.sat" = .{ .ret_len = 1, @@ -3441,7 +3714,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ssub.sat" = .{ .ret_len = 1, @@ -3450,7 +3723,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"usub.sat" = .{ .ret_len = 1, @@ -3459,7 +3732,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sshl.sat" = .{ .ret_len = 1, @@ -3468,7 +3741,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"ushl.sat" = .{ .ret_len = 1, @@ -3477,7 +3750,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.fix" = .{ @@ -3488,7 +3761,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.fix" = .{ .ret_len = 1, @@ -3498,7 +3771,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"smul.fix.sat" = .{ .ret_len = 1, @@ -3508,7 +3781,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"umul.fix.sat" = .{ .ret_len = 1, @@ -3518,7 +3791,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"sdiv.fix" = .{ .ret_len = 1, @@ -3528,7 +3801,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"udiv.fix" = .{ .ret_len = 1, @@ -3538,7 +3811,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"sdiv.fix.sat" = .{ .ret_len = 1, @@ -3548,7 +3821,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"udiv.fix.sat" = .{ .ret_len = 1, @@ -3558,7 +3831,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .canonicalize = .{ @@ -3567,7 +3840,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .fmuladd = .{ .ret_len = 1, @@ -3577,7 +3850,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.add" = .{ @@ -3586,7 +3859,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fadd" = .{ .ret_len = 1, @@ -3595,7 +3868,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 2 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.mul" = .{ .ret_len = 1, @@ -3603,7 +3876,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmul" = .{ .ret_len = 1, @@ -3612,7 +3885,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 2 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.and" = .{ .ret_len = 1, @@ -3620,7 +3893,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.or" = .{ .ret_len = 1, @@ -3628,7 +3901,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.xor" = .{ .ret_len = 1, @@ -3636,7 +3909,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.smax" = .{ .ret_len = 1, @@ -3644,7 +3917,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.smin" = .{ .ret_len = 1, @@ -3652,7 +3925,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.umax" = .{ .ret_len = 1, @@ -3660,7 +3933,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.umin" = .{ .ret_len = 1, @@ -3668,7 +3941,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmax" = .{ .ret_len = 1, @@ -3676,7 +3949,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmin" = .{ .ret_len = 1, @@ -3684,7 +3957,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fmaximum" = .{ .ret_len = 1, @@ -3692,7 +3965,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.reduce.fminimum" = .{ .ret_len = 1, @@ -3700,7 +3973,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches_scalar = 1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.insert" = .{ .ret_len = 1, @@ -3710,7 +3983,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i64 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"vector.extract" = .{ .ret_len = 1, @@ -3719,7 +3992,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i64 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"is.fpclass" = .{ @@ -3729,7 +4002,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nocreateundeforpoison, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"var.annotation" = .{ @@ -3814,7 +4087,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .expect = .{ .ret_len = 1, @@ -3823,7 +4096,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"expect.with.probability" = .{ .ret_len = 1, @@ -3833,7 +4106,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .assume = .{ .ret_len = 0, @@ -3848,7 +4121,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.test" = .{ .ret_len = 1, @@ -3857,7 +4130,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .ptr } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.checked.load" = .{ .ret_len = 2, @@ -3868,7 +4141,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"type.checked.load.relative" = .{ .ret_len = 2, @@ -3879,7 +4152,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i32 } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"arithmetic.fence" = .{ .ret_len = 1, @@ -3887,12 +4160,12 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .matches = 0 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .donothing = .{ .ret_len = 0, .params = &.{}, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"load.relative" = .{ .ret_len = 1, @@ -3914,7 +4187,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .i1 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .ptrmask = .{ .ret_len = 1, @@ -3923,7 +4196,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .matches = 0 } }, .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"threadlocal.address" = .{ .ret_len = 1, @@ -3931,14 +4204,14 @@ pub const Intrinsic = enum { .{ .kind = .overloaded, .attrs = &.{.nonnull} }, .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .vscale = .{ .ret_len = 1, .params = &.{ .{ .kind = .overloaded }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"dbg.declare" = .{ @@ -3948,7 +4221,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .metadata } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"dbg.value" = .{ .ret_len = 0, @@ -3957,7 +4230,7 @@ pub const Intrinsic = enum { .{ .kind = .{ .type = .metadata } }, .{ .kind = .{ .type = .metadata } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.x" = .{ @@ -3965,42 +4238,42 @@ pub const Intrinsic = enum { .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.y" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workitem.id.z" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.x" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.y" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.workgroup.id.z" = .{ .ret_len = 1, .params = &.{ .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"amdgcn.dispatch.ptr" = .{ .ret_len = 1, @@ -4010,7 +4283,7 @@ pub const Intrinsic = enum { .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }}, }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = .all(.none) } }, }, .@"nvvm.read.ptx.sreg.tid.x" = .{ @@ -4085,7 +4358,7 @@ pub const Intrinsic = enum { .{ .kind = .overloaded }, .{ .kind = .{ .type = .i32 } }, }, - .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .all(.none) } }, }, .@"wasm.memory.grow" = .{ .ret_len = 1, @@ -4166,6 +4439,10 @@ pub const Function = struct { self.ptr(builder).attributes = new_function_attributes; } + pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes { + return self.ptr(builder).attributes; + } + pub fn setSection(self: Index, section: String, builder: *Builder) void { self.ptr(builder).section = section; } @@ -4487,7 +4764,7 @@ pub const Function = struct { } pub fn toValue(self: Instruction.Index) Value { - return @fromBackingInt(@intCast(@backingInt(self))); + return @fromBackingInt(@backingInt(self)); } pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool { @@ -4679,7 +4956,7 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, wip.builder), .fneg, .@"fneg fast", - => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip), + => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip), .getelementptr, .@"getelementptr inbounds", => { @@ -4871,7 +5148,7 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, builder), .fneg, .@"fneg fast", - => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOf(function_index, builder), + => @as(Value, @fromBackingInt(instruction.data)).typeOf(function_index, builder), .getelementptr, .@"getelementptr inbounds", => { @@ -4963,7 +5240,7 @@ pub const Function = struct { pub fn fromMetadata(metadata: Metadata) Weights { assert(metadata.kind == .node); - return @fromBackingInt(@intCast(metadata.index)); + return @fromBackingInt(metadata.index); } pub fn toMetadata(weights: Weights) Metadata { @@ -5156,7 +5433,7 @@ pub const Function = struct { assert(argument.tag == .arg); assert(argument.data == index); - const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); + const argument_index: Instruction.Index = @fromBackingInt(index); return argument_index.toValue(); } @@ -5202,7 +5479,7 @@ pub const Function = struct { Type, Value, Instruction.BrCond.Weights, - => @fromBackingInt(@intCast(value)), + => @fromBackingInt(value), MemoryAccessInfo, Instruction.Alloca.Info, Instruction.Call.Info, @@ -5327,7 +5604,7 @@ pub const WipFunction = struct { assert(argument.tag == .arg); assert(argument.data == index); - const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); + const argument_index: Instruction.Index = @fromBackingInt(index); return argument_index.toValue(); } @@ -6414,24 +6691,24 @@ pub const WipFunction = struct { errdefer function.instructions.shrinkRetainingCapacity(0); { - var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0)); + var final_instruction_index: Instruction.Index = @fromBackingInt(0); for (0..params_len) |param_index| { instructions.items[param_index] = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); } for (blocks, self.blocks.items) |*final_block, current_block| { assert(current_block.incoming == current_block.branches); final_block.instruction = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); for (current_block.instructions.items) |instruction| { instructions.items[@backingInt(instruction)] = final_instruction_index; - final_instruction_index = @fromBackingInt(@intCast(@backingInt(final_instruction_index) + 1)); + final_instruction_index = @fromBackingInt(@backingInt(final_instruction_index) + 1); } } } var wip_name: struct { - next_name: String = @fromBackingInt(@intCast(0)), + next_name: String = @fromBackingInt(0), next_unique_name: std.AutoHashMap(String, String), builder: *Builder, @@ -6440,19 +6717,19 @@ pub const WipFunction = struct { .none => return .none, .empty => { assert(wip_name.next_name != .none); - defer wip_name.next_name = @fromBackingInt(@intCast(@backingInt(wip_name.next_name) + 1)); + defer wip_name.next_name = @fromBackingInt(@backingInt(wip_name.next_name) + 1); return wip_name.next_name; }, _ => { assert(!name.isAnon()); const gop = try wip_name.next_unique_name.getOrPut(name); if (!gop.found_existing) { - gop.value_ptr.* = @fromBackingInt(@intCast(0)); + gop.value_ptr.* = @fromBackingInt(0); return name; } while (true) { - gop.value_ptr.* = @fromBackingInt(@intCast(@backingInt(gop.value_ptr.*) + 1)); + gop.value_ptr.* = @fromBackingInt(@backingInt(gop.value_ptr.*) + 1); const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{ name.fmtRaw(wip_name.builder), sep, @@ -6460,7 +6737,7 @@ pub const WipFunction = struct { }); const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name); if (!unique_gop.found_existing) { - unique_gop.value_ptr.* = @fromBackingInt(@intCast(0)); + unique_gop.value_ptr.* = @fromBackingInt(0); return unique_name; } } @@ -6702,7 +6979,7 @@ pub const WipFunction = struct { .fneg, .@"fneg fast", .ret, - => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))), + => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))), .getelementptr, .@"getelementptr inbounds", => { @@ -7079,7 +7356,7 @@ pub const WipFunction = struct { Type, Value, Instruction.BrCond.Weights, - => @fromBackingInt(@intCast(value)), + => @fromBackingInt(value), MemoryAccessInfo, Instruction.Alloca.Info, Instruction.Call.Info, @@ -7268,7 +7545,7 @@ pub const Constant = enum(u32) { no_init = (1 << 30) - 1, _, - const first_global: Constant = @fromBackingInt(@intCast(1 << 29)); + const first_global: Constant = @fromBackingInt(1 << 29); pub const Tag = enum(u7) { positive_integer, @@ -7405,7 +7682,18 @@ pub const Constant = enum(u32) { val: Constant, type: Type, - pub const Signedness = enum { unsigned, signed, unneeded }; + pub const Signedness = enum { + unsigned, + signed, + unneeded, + + pub fn fromStdLang(signedness: std.lang.Signedness) Signedness { + return switch (signedness) { + .unsigned => .unsigned, + .signed => .signed, + }; + } + }; }; pub const GetElementPtr = struct { @@ -7444,11 +7732,11 @@ pub const Constant = enum(u32) { return if (@backingInt(self) < @backingInt(first_global)) .{ .constant = @intCast(@backingInt(self)) } else - .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) }; + .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) }; } pub fn toValue(self: Constant) Value { - return @fromBackingInt(@intCast(Value.first_constant + @backingInt(self))); + return @fromBackingInt(Value.first_constant + @backingInt(self)); } pub fn typeOf(self: Constant, builder: *Builder) Type { @@ -7474,7 +7762,7 @@ pub const Constant = enum(u32) { .zeroinitializer, .undef, .poison, - => @fromBackingInt(@intCast(item.data)), + => @fromBackingInt(item.data), .structure, .packed_structure, .array, @@ -7482,7 +7770,7 @@ pub const Constant = enum(u32) { => builder.constantExtraData(Aggregate, item.data).type, .splat => builder.constantExtraData(Splat, item.data).type, .string => builder.arrayTypeAssumeCapacity( - @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len, + @as(String, @fromBackingInt(item.data)).slice(builder).?.len, .i8, ), .blockaddress => builder.ptrTypeAssumeCapacity( @@ -7491,7 +7779,7 @@ pub const Constant = enum(u32) { ), .dso_local_equivalent, .no_cfi, - => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data))) + => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data)) .ptrConst(builder).global.ptrConst(builder).addr_space), .trunc, .ptrtoint, @@ -7802,7 +8090,7 @@ pub const Constant = enum(u32) { try w.writeByte('>'); }, .string => try w.print("c{f}", .{ - @as(String, @fromBackingInt(@intCast(item.data))).fmtQ(data.builder), + @as(String, @fromBackingInt(item.data)).fmtQ(data.builder), }), .blockaddress => |tag| { const extra = data.builder.constantExtraData(BlockAddress, item.data); @@ -7816,7 +8104,7 @@ pub const Constant = enum(u32) { .dso_local_equivalent, .no_cfi, => |tag| { - const function: Function.Index = @fromBackingInt(@intCast(item.data)); + const function: Function.Index = @fromBackingInt(item.data); try w.print("{s} {f}", .{ @tagName(tag), function.ptrConst(data.builder).global.fmt(data.builder), @@ -7920,9 +8208,9 @@ pub const Value = enum(u32) { metadata: Metadata, } { return if (@backingInt(self) < first_constant) - .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) } + .{ .instruction = @fromBackingInt(@backingInt(self)) } else if (@backingInt(self) < first_metadata) - .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) } + .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) } else .{ .metadata = @bitCast(@backingInt(self) - first_metadata) }; } @@ -8016,7 +8304,7 @@ pub const Metadata = packed struct(u32) { return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false }; } pub fn toValue(metadata: Metadata) Value { - return @fromBackingInt(@intCast(Value.first_metadata + @as(u32, @bitCast(metadata)))); + return @fromBackingInt(Value.first_metadata + @as(u32, @bitCast(metadata))); } pub const String = enum(u32) { @@ -8032,7 +8320,7 @@ pub const Metadata = packed struct(u32) { pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String { return switch (metadata) { .none => null, - else => @fromBackingInt(@intCast(@backingInt(metadata))), + else => @fromBackingInt(@backingInt(metadata)), }; } pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional { @@ -8040,7 +8328,7 @@ pub const Metadata = packed struct(u32) { } }; pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional { - return @fromBackingInt(@intCast(@backingInt(metadata))); + return @fromBackingInt(@backingInt(metadata)); } pub fn toMetadata(metadata: Metadata.String) Metadata { return .{ .index = @intCast(@backingInt(metadata)), .kind = .string }; @@ -8077,7 +8365,7 @@ pub const Metadata = packed struct(u32) { }; pub fn toString(metadata: Metadata) Metadata.String { assert(metadata.kind == .string); - return @fromBackingInt(@intCast(metadata.index)); + return @fromBackingInt(metadata.index); } pub const Tag = enum(u6) { @@ -8542,7 +8830,7 @@ pub const Metadata = packed struct(u32) { try w.writeByte(')'); }, .constant => try Constant.format(.{ - .constant = @fromBackingInt(@intCast(node_item.data)), + .constant = @fromBackingInt(node_item.data), .builder = builder, .flags = data.specialized orelse .{}, }, w), @@ -8744,7 +9032,7 @@ pub fn init(options: Options) Allocator.Error!Builder { .string_bytes = .empty, .types = .empty, - .next_unnamed_type = @fromBackingInt(@intCast(0)), + .next_unnamed_type = @fromBackingInt(0), .next_unique_type_id = .empty, .type_map = .empty, .type_items = .empty, @@ -8758,7 +9046,7 @@ pub fn init(options: Options) Allocator.Error!Builder { .function_attributes_set = .empty, .globals = .empty, - .next_unnamed_global = @fromBackingInt(@intCast(0)), + .next_unnamed_global = @fromBackingInt(0), .next_replaced_global = .none, .next_unique_global_id = .empty, .aliases = .empty, @@ -8815,7 +9103,7 @@ pub fn init(options: Options) Allocator.Error!Builder { assert(self.intTypeAssumeCapacity(bits) == @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); inline for (.{ 0, 4 }) |addr_space_index| { - const addr_space: AddrSpace = @fromBackingInt(@intCast(addr_space_index)); + const addr_space: AddrSpace = @fromBackingInt(addr_space_index); assert(self.ptrTypeAssumeCapacity(addr_space) == @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")}))); } @@ -9092,17 +9380,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr return @backingInt(lhs_kind) < @backingInt(rhs_kind); } }.lessThan); - return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes)))); + return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes))); } pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes { try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1); - const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast( + const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast( fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| last + 1 else 0], - )))); + ))); _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes); return function_attributes; @@ -9121,7 +9409,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa if (name == .empty) { id = self.next_unnamed_global; assert(id != self.next_replaced_global); - self.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(id) + 1)); + self.next_unnamed_global = @fromBackingInt(@backingInt(id) + 1); } while (true) { const global_gop = self.globals.getOrPutAssumeCapacity(id); @@ -10058,7 +10346,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void continue; }, .br => |tag| { - const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data)); + const target: Function.Block.Index = @fromBackingInt(instruction.data); try w.print(" {s} {f}", .{ @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }), }); @@ -10187,7 +10475,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void .fneg, .@"fneg fast", => |tag| { - const val: Value = @fromBackingInt(@intCast(instruction.data)); + const val: Value = @fromBackingInt(instruction.data); try w.print(" %{f} = {s} {f}", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -10288,7 +10576,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void } }, .ret => |tag| { - const val: Value = @fromBackingInt(@intCast(instruction.data)); + const val: Value = @fromBackingInt(instruction.data); try w.print(" {s} {f}", .{ @tagName(tag), val.fmt(function_index, self, .{ .percent = true }), @@ -11020,7 +11308,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { if (name == .empty) { id = self.next_unnamed_type; assert(id != .none); - self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1)); + self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1); } else assert(!name.isAnon()); while (true) { const type_gop = self.types.getOrPutAssumeCapacity(id); @@ -11135,7 +11423,7 @@ fn typeExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - String, Type => @fromBackingInt(@intCast(value)), + String, Type => @fromBackingInt(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; return .{ @@ -11746,7 +12034,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: return std.meta.eql(lhs_key.cast, rhs_extra); } }; - const data = Key{ .tag = tag, .cast = .{ .val = val, .type = ty } }; + const data: Key = .{ .tag = tag, .cast = .{ .val = val, .type = ty } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); if (!gop.found_existing) { gop.key_ptr.* = {}; @@ -11828,10 +12116,10 @@ fn gepConstAssumeCapacity( std.mem.eql(Constant, lhs_key.indices, rhs_indices); } }; - const data = Key{ + const data: Key = .{ .type = ty, .base = base, - .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none, + .inrange = if (inrange) |index| @fromBackingInt(index) else .none, .indices = indices, }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); @@ -11885,7 +12173,7 @@ fn binConstAssumeCapacity( return std.meta.eql(lhs_key.extra, rhs_extra); } }; - const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } }; + const data: Key = .{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); if (!gop.found_existing) { gop.key_ptr.* = {}; @@ -11924,8 +12212,8 @@ fn asmConstAssumeCapacity( } }; - const data = Key{ - .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))), + const data: Key = .{ + .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))), .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints }, }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); @@ -12073,7 +12361,7 @@ fn constantExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(@intCast(value)), + String, Type, Constant, Function.Index, Function.Block.Index => @fromBackingInt(value), Constant.GetElementPtr.Info => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; @@ -12151,7 +12439,7 @@ fn metadataExtraDataTrail( ) |field_name, field_type, value| @field(result, field_name) = switch (field_type) { u32 => value, - Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(@intCast(value)), + Metadata.String, Metadata.String.Optional, Variable.Index, Value => @fromBackingInt(value), Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field_type)), }; @@ -12759,8 +13047,8 @@ fn debugSubprogramAssumeCapacity( compile_unit: ?Metadata, ) Metadata { assert(!self.strip); - const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) + - @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)))); + const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) + + @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))); return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{ .file = .wrap(file), .name = .wrap(name), @@ -13345,7 +13633,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata { pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool { if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; - const rhs_data: Constant = @fromBackingInt(@intCast(ctx.builder.metadata_items.items(.data)[rhs_index])); + const rhs_data: Constant = @fromBackingInt(ctx.builder.metadata_items.items(.data)[rhs_index]); return rhs_data == lhs_key; } }; @@ -13577,6 +13865,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco switch (attr_index.toAttribute(self)) { .zeroext, .signext, + .noext, .inreg, .@"noalias", .nocapture, @@ -13594,11 +13883,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .readnone, .readonly, .writeonly, + .writable, + .dead_on_unwind, .alwaysinline, .builtin, .cold, .convergent, - .disable_sanitizer_information, + .disable_sanitizer_instrumentation, .fn_ret_thunk_extern, .hot, .inlinehint, @@ -13607,6 +13898,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .naked, .nobuiltin, .nocallback, + .nodivergencesource, .noduplicate, .noimplicitfloat, .@"noinline", @@ -13623,6 +13915,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .nosanitize_bounds, .nosanitize_coverage, .null_pointer_is_valid, + .optdebug, .optforfuzzing, .optnone, .optsize, @@ -13633,18 +13926,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .sanitize_thread, .sanitize_hwaddress, .sanitize_memtag, + .sanitize_realtime, + .sanitize_realtime_blocking, + .sanitize_alloc_token, .speculative_load_hardening, .speculatable, .ssp, .sspstrong, .sspreq, .strictfp, + .denormal_fpenv, .nocf_check, .shadowcallstack, .mustprogress, - .no_sanitize_address, - .no_sanitize_hwaddress, - .sanitize_address_dyninit, + .nooutline, + .nocreateundeforpoison, => { try record.ensureUnusedCapacity(self.gpa, 2); record.appendAssumeCapacity(0); @@ -13670,6 +13966,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco record.appendAssumeCapacity(@backingInt(kind)); record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0); }, + .captures => |captures| { + try record.ensureUnusedCapacity(self.gpa, 3); + record.appendAssumeCapacity(1); + record.appendAssumeCapacity(@backingInt(kind)); + record.appendAssumeCapacity(@as(u32, @bitCast(captures))); + }, .dereferenceable, .dereferenceable_or_null, => |size| { @@ -13684,6 +13986,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco record.appendAssumeCapacity(@backingInt(kind)); record.appendAssumeCapacity(@as(u32, @bitCast(fpclass))); }, + .initializes => @panic("TODO"), + .dead_on_return => @panic("TODO"), + .range => @panic("TODO"), .allockind => |allockind| { try record.ensureUnusedCapacity(self.gpa, 3); record.appendAssumeCapacity(1); @@ -14099,7 +14404,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco } }, .string => { - const str: String = @fromBackingInt(@intCast(data)); + const str: String = @fromBackingInt(data); if (str == .none) { try constants_block.writeAbbrev(ConstantsBlock.Null{}); } else { @@ -14226,7 +14531,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .dso_local_equivalent, .no_cfi, => |tag| { - const function: Function.Index = @fromBackingInt(@intCast(data)); + const function: Function.Index = @fromBackingInt(data); try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{ .code = switch (tag) { .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT, @@ -14609,7 +14914,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }, metadata_adapter); }, .constant => { - const constant: Constant = @fromBackingInt(@intCast(data)); + const constant: Constant = @fromBackingInt(data); try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{ .ty = constant.typeOf(self), .constant = constant, @@ -14778,7 +15083,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco var adapter: FunctionAdapter = .{ .metadata_adapter = metadata_adapter, .func = &func, - .instruction_index = @fromBackingInt(@intCast(0)), + .instruction_index = @fromBackingInt(0), }; // Emit function level metadata block @@ -14789,7 +15094,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco for (func.debug_values) |value| { try metadata_block.writeAbbrev(MetadataBlock.Value{ .ty = value.typeOf(@fromBackingInt(@intCast(func_index)), self), - .value = @fromBackingInt(@intCast(adapter.getValueIndex(value.toValue()))), + .value = @fromBackingInt(adapter.getValueIndex(value.toValue())), }); } @@ -15071,10 +15376,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }); }, .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), }), .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), .fast_math = FastMath.fast, }), .extractvalue => { @@ -15274,7 +15579,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco try function_block.writeUnabbrev(16, record.items); }, .ret => try function_block.writeAbbrev(FunctionBlock.Ret{ - .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), + .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), }), .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}), .atomicrmw => { -- 2.54.0 From 0c0be6da880fd1a6bdd3266125d6c5bcaac2803f Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 26 Jun 2026 01:08:08 -0400 Subject: [PATCH 048/215] llvm: implement c cabi for s390x Closes #35799 --- CMakeLists.txt | 1 + src/codegen/aarch64/abi.zig | 2 +- src/codegen/llvm/FuncGen.zig | 31 +++++++++- src/codegen/s390x/abi.zig | 90 +++++++++++++++++++++++++++ test/c_abi/cfuncs.c | 12 ---- test/c_abi/main.zig | 115 +---------------------------------- 6 files changed, 121 insertions(+), 130 deletions(-) create mode 100644 src/codegen/s390x/abi.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f144cd68374ec7c0ec8c7ba7964cde06943d88a..ad4d8bea72ee199d041ef28559b536de2f20f7e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,6 +358,7 @@ set(ZIG_STAGE2_SOURCES src/codegen/c/type/render_defs.zig src/codegen/llvm.zig src/codegen/llvm/bindings.zig + src/codegen/s390x/abi.zig src/crash_report.zig src/dev.zig src/libs/freebsd.zig diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index dcd192da8395fc6fca07c101aebff596bc4e99cc..942e4d0660d79fd8bb0e204714586dd7878b3ebe 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assert = std.debug.assert; const std = @import("std"); const InternPool = @import("../../InternPool.zig"); const Type = @import("../../Type.zig"); diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 5e05a779220d002a88fd128d5057f5eef70e1a4a..156aa875926d6d3d55341b2eac6d1e8f93e18972 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -6808,6 +6808,24 @@ const ParamTypeIterator = struct { }, } }, + .s390x_sysv, .s390x_sysv_vx => { + it.zig_index += 1; + switch (s390x_c_abi.classifyType(ty, .arg, zcu)) { + .none => return .no_bits, + .double_or_float, .vector, .simple => { + it.llvm_index += 1; + return .byval; + }, + .simple_aggregate => { + it.llvm_index += 1; + return .abi_sized_int; + }, + .pointer => { + it.llvm_index += 1; + return .byref_mut; + }, + } + }, .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) { .direct => |scalar_ty| { if (isScalar(zcu, ty)) { @@ -7086,6 +7104,12 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; }, }, + .s390x_sysv, .s390x_sysv_vx => return switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { + .none => .void, + .double_or_float, .vector, .simple => .by_val, + .simple_aggregate => unreachable, + .pointer => .sret, + }, .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) { .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { assert(!isByRef(ret_ty, zcu)); @@ -7823,12 +7847,13 @@ const Builder = std.zig.llvm.Builder; const assert = std.debug.assert; const math = std.math; -const x86_64_abi = @import("../x86_64/abi.zig"); -const wasm_c_abi = @import("../wasm/abi.zig"); const aarch64_c_abi = @import("../aarch64/abi.zig"); const arm_c_abi = @import("../arm/abi.zig"); -const riscv_c_abi = @import("../riscv64/abi.zig"); const mips_c_abi = @import("../mips/abi.zig"); +const riscv_c_abi = @import("../riscv64/abi.zig"); +const s390x_c_abi = @import("../s390x/abi.zig"); +const wasm_c_abi = @import("../wasm/abi.zig"); +const x86_64_abi = @import("../x86_64/abi.zig"); const Zcu = @import("../../Zcu.zig"); const Air = @import("../../Air.zig"); diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig new file mode 100644 index 0000000000000000000000000000000000000000..6fb81d3e6b8792566b9c69156ca63a67ed788299 --- /dev/null +++ b/src/codegen/s390x/abi.zig @@ -0,0 +1,90 @@ +const assert = std.debug.assert; +const std = @import("std"); +const InternPool = @import("../../InternPool.zig"); +const Type = @import("../../Type.zig"); +const Zcu = @import("../../Zcu.zig"); + +pub const Context = enum { ret, arg }; + +pub const Class = enum { + none, + double_or_float, + vector, + simple, + simple_aggregate, + pointer, +}; + +pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class { + tag: switch (ty.zigTypeTag(zcu)) { + .type, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_union, + .error_set, + .@"fn", + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + .spirv, + => unreachable, + .void, .noreturn => return .none, + .bool => return .simple, + .int, .@"enum" => return switch (ty.intInfo(zcu).bits) { + 0 => .none, + 1...64 => .simple, + else => .pointer, + }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + 16, 32, 64 => .double_or_float, + else => .pointer, + }, + .pointer, .optional => return .simple, + .array => switch (ty.arrayLen(zcu)) { + 0 => return .none, + 1 => switch (context) { + .ret => {}, + .arg => return classifyType(ty.childType(zcu), context, zcu), + }, + else => {}, + }, + .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) { + .auto => unreachable, + .@"extern" => switch (context) { + .ret => {}, + .arg => { + var class: Class = .none; + for (0..switch (tag) { + else => unreachable, + .@"struct" => ty.structFieldCount(zcu), + .@"union" => ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu), + }) |field_index| { + switch (tag) { + else => unreachable, + .@"struct" => if (ty.structFieldIsComptime(field_index, zcu)) continue, + .@"union" => {}, + } + const field_class = classifyType(ty.fieldType(field_index, zcu), context, zcu); + if (field_class == .none) continue; + if (class != .none) break :tag; + class = field_class; + } + return class; + }, + }, + .@"packed" => return classifyType(ty.backingIntType(zcu), context, zcu), + }, + .vector => return if (ty.abiSize(zcu) <= 16) .vector else .pointer, + } + return switch (ty.abiSize(zcu)) { + 0 => .none, + 1, 2, 4, 8 => switch (context) { + .ret => .pointer, + .arg => .simple_aggregate, + }, + else => .pointer, + }; +} diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index cfd3872c94ef750e6663f6e9c4d186516c76beb7..acd8c258649e3cccadadbd4390d8f9b0cf0999a6 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -15564,7 +15564,6 @@ void run_c_tests(void) { #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct Struct_i32_i32 s = {1, 2}; zig_struct_i32_i32(s); @@ -15573,13 +15572,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct BigStruct s = {1, 2, 3, 4, 5}; zig_big_struct(s); @@ -15588,7 +15585,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef ZIG_NO_I128 { @@ -15613,7 +15609,6 @@ void run_c_tests(void) { #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct SplitStructInts s = {1234, 100, 1337}; zig_split_struct_ints(s); @@ -15623,13 +15618,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct MedStructMixed s = {1234, 100.0f, 1337.0f}; zig_med_struct_mixed(s); @@ -15638,14 +15631,12 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct SplitStructMixed s = {1234, 100, 1337.0f}; zig_split_struct_mixed(s); @@ -15655,13 +15646,11 @@ void run_c_tests(void) { #endif #endif #endif -#endif #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 #ifndef __powerpc__ -#ifndef __s390x__ { struct BigStruct s = {30, 31, 32, 33, 34}; struct BigStruct res = zig_big_struct_both(s); @@ -15674,7 +15663,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #endif { diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 974adf898c9fd092396d279bf34a22f050235d73..387eeb88c20b4ebfa9646ff10fde7322db299302 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -13,7 +13,7 @@ const expectEqual = std.testing.expectEqual; const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and builtin.cpu.arch != .hexagon and - builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460 + builtin.cpu.arch != .s390x; const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc); const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc; @@ -5136,7 +5136,6 @@ test "@Vector(24, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u8(); try expect(v[0] == 57); @@ -5220,7 +5219,6 @@ test "@Vector(32, u8)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u8(); try expect(v[0] == 69); @@ -5330,7 +5328,6 @@ test "@Vector(48, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u8(); try expect(v[0] == 29); @@ -5473,7 +5470,6 @@ test "@Vector(64, u8)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u8(); try expect(v[0] == 53); @@ -5668,7 +5664,6 @@ test "@Vector(96, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u8(); try expect(v[0] == 82); @@ -5931,7 +5926,6 @@ test "@Vector(128, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u8(); try expect(v[0] == 30); @@ -6296,7 +6290,6 @@ test "@Vector(192, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_192_u8(); try expect(v[0] == 70); @@ -6797,7 +6790,6 @@ test "@Vector(256, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_256_u8(); try expect(v[0] == 66); @@ -7502,7 +7494,6 @@ test "@Vector(384, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_384_u8(); try expect(v[0] == 46); @@ -8479,7 +8470,6 @@ test "@Vector(512, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_512_u8(); try expect(v[0] == 38); @@ -9250,7 +9240,6 @@ test "@Vector(12, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_u16(); try expect(v[0] == 121); @@ -9300,7 +9289,6 @@ test "@Vector(16, u16)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u16(); try expect(v[0] == 177); @@ -9366,7 +9354,6 @@ test "@Vector(24, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u16(); try expect(v[0] == 257); @@ -9450,7 +9437,6 @@ test "@Vector(32, u16)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u16(); try expect(v[0] == 369); @@ -9560,7 +9546,6 @@ test "@Vector(48, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u16(); try expect(v[0] == 529); @@ -9704,7 +9689,6 @@ test "@Vector(64, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u16(); try expect(v[0] == 753); @@ -9899,7 +9883,6 @@ test "@Vector(96, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u16(); try expect(v[0] == 1082); @@ -10162,7 +10145,6 @@ test "@Vector(128, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u16(); try expect(v[0] == 1530); @@ -10527,7 +10509,6 @@ test "@Vector(192, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_192_u16(); try expect(v[0] == 2170); @@ -11028,7 +11009,6 @@ test "@Vector(256, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_256_u16(); try expect(v[0] == 3066); @@ -11445,7 +11425,6 @@ test "@Vector(6, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_u32(); try expect(v[0] == 53); @@ -11481,7 +11460,6 @@ test "@Vector(8, u32)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_u32(); try expect(v[0] == 81); @@ -11524,7 +11502,6 @@ test "@Vector(12, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_u32(); try expect(v[0] == 121); @@ -11574,7 +11551,6 @@ test "@Vector(16, u32)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u32(); try expect(v[0] == 177); @@ -11640,7 +11616,6 @@ test "@Vector(24, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_u32(); try expect(v[0] == 257); @@ -11725,7 +11700,6 @@ test "@Vector(32, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u32(); try expect(v[0] == 369); @@ -11835,7 +11809,6 @@ test "@Vector(48, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_u32(); try expect(v[0] == 529); @@ -11979,7 +11952,6 @@ test "@Vector(64, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u32(); try expect(v[0] == 753); @@ -12174,7 +12146,6 @@ test "@Vector(96, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_u32(); try expect(v[0] == 1082); @@ -12437,7 +12408,6 @@ test "@Vector(128, u32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_u32(); try expect(v[0] == 1530); @@ -12644,7 +12614,6 @@ test "@Vector(3, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_3_u64(); try expect(v[0] == 19); @@ -12673,7 +12642,6 @@ test "@Vector(4, u64)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_4_u64(); try expect(v[0] == 33); @@ -12740,7 +12708,6 @@ test "@Vector(8, u64)" { if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_u64(); try expect(v[0] == 81); @@ -12832,7 +12799,6 @@ test "@Vector(16, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_u64(); try expect(v[0] == 177); @@ -12981,7 +12947,6 @@ test "@Vector(32, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_u64(); try expect(v[0] == 369); @@ -13233,7 +13198,6 @@ test "@Vector(64, u64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_u64(); try expect(v[0] == 753); @@ -13449,7 +13413,6 @@ test "@Vector(6, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_f32(); try expect(v[0] == 53); @@ -13486,7 +13449,6 @@ test "@Vector(8, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_8_f32(); try expect(v[0] == 81); @@ -13529,7 +13491,6 @@ test "@Vector(12, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_f32(); try expect(v[0] == 121); @@ -13580,7 +13541,6 @@ test "@Vector(16, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_f32(); try expect(v[0] == 177); @@ -13646,7 +13606,6 @@ test "@Vector(24, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_f32(); try expect(v[0] == 257); @@ -13731,7 +13690,6 @@ test "@Vector(32, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_f32(); try expect(v[0] == 369); @@ -13841,7 +13799,6 @@ test "@Vector(48, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_f32(); try expect(v[0] == 529); @@ -13985,7 +13942,6 @@ test "@Vector(64, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_f32(); try expect(v[0] == 753); @@ -14180,7 +14136,6 @@ test "@Vector(96, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_96_f32(); try expect(v[0] == 1082); @@ -14443,7 +14398,6 @@ test "@Vector(128, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_128_f32(); try expect(v[0] == 1530); @@ -14651,7 +14605,6 @@ test "@Vector(3, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_3_f64(); try expect(v[0] == 19); @@ -14680,7 +14633,6 @@ test "@Vector(4, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_4_f64(); @@ -14714,7 +14666,6 @@ test "@Vector(6, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_6_f64(); try expect(v[0] == 53); @@ -14750,7 +14701,6 @@ test "@Vector(8, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_8_f64(); @@ -14794,7 +14744,6 @@ test "@Vector(12, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_12_f64(); try expect(v[0] == 121); @@ -14845,7 +14794,6 @@ test "@Vector(16, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_16_f64(); try expect(v[0] == 177); @@ -14911,7 +14859,6 @@ test "@Vector(24, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_24_f64(); try expect(v[0] == 257); @@ -14996,7 +14943,6 @@ test "@Vector(32, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_32_f64(); try expect(v[0] == 369); @@ -15106,7 +15052,6 @@ test "@Vector(48, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_48_f64(); try expect(v[0] == 529); @@ -15250,7 +15195,6 @@ test "@Vector(64, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const v = c_ret_vector_64_f64(); try expect(v[0] == 753); @@ -15345,7 +15289,6 @@ extern fn c_test_struct_u8() void; test "struct u8" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u8(); @@ -15377,7 +15320,6 @@ test "struct u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8(); @@ -15412,7 +15354,6 @@ test "struct u8, u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8(); @@ -15450,7 +15391,6 @@ test "struct u8, u8, u8, u8" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8_u8(); @@ -15481,7 +15421,6 @@ extern fn c_test_struct_u16() void; test "struct u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u16(); @@ -15513,7 +15452,6 @@ test "struct u16, u16" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16(); @@ -15549,7 +15487,6 @@ test "struct u16, u16, u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16_u16(); @@ -15588,7 +15525,6 @@ test "struct u16, u16, u16, u16" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16_u16_u16(); @@ -15619,7 +15555,6 @@ extern fn c_test_struct_u32() void; test "struct u32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u32(); @@ -15651,7 +15586,6 @@ test "struct u32, u32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u32_u32(); @@ -15686,7 +15620,6 @@ test "struct u32, u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32(); try expect(s.a == 8); @@ -15723,7 +15656,6 @@ test "struct u32, u32, u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32_u32(); try expect(s.a == 10); @@ -15753,7 +15685,6 @@ extern fn c_test_struct_u64() void; test "struct u64" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_u64(); @@ -15831,7 +15762,6 @@ extern fn c_test_struct_u64_u64() void; test "struct u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64(); try expect(s.a == 21); @@ -15872,7 +15802,6 @@ test "struct u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64(); try expect(s.a == 8); @@ -15908,7 +15837,6 @@ test "struct u64, u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64_u64(); try expect(s.a == 10); @@ -15938,7 +15866,6 @@ extern fn c_test_struct_f32() void; test "struct f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32(); @@ -15971,7 +15898,6 @@ test "struct f32, f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32_f32(); @@ -16007,7 +15933,6 @@ test "struct f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32(); try expect(s.a == 8); @@ -16045,7 +15970,6 @@ test "struct f32, f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32_f32(); try expect(s.a == 10); @@ -16085,7 +16009,6 @@ test "struct f32, f32, f32, f32, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32_f32_f32_f32(); try expect(s.a == 12); @@ -16120,7 +16043,6 @@ test "struct f32 align(8)" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_f32a8(); @@ -16154,7 +16076,6 @@ test "struct f32 align(8), f32 align(8)" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_f32a8_f32a8(); @@ -16188,7 +16109,6 @@ test "struct {f32, f32}, f32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32f32_f32(); try expect(s.a.b == 1.0); @@ -16222,7 +16142,6 @@ test "struct f32, {f32, f32}" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f32_f32f32(); try expect(s.a == 1.0); @@ -16252,7 +16171,6 @@ test "struct f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f64(); @@ -16283,7 +16201,6 @@ test "struct f64, f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64(); try expect(s.a == 6); @@ -16316,7 +16233,6 @@ test "struct f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64(); try expect(s.a == 8); @@ -16352,7 +16268,6 @@ test "struct f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64(); try expect(s.a == 10); @@ -16391,7 +16306,6 @@ test "struct f64, f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64_f64(); try expect(s.a == 12); @@ -16431,7 +16345,6 @@ test "struct{u32,union{u32,struct{u32,u32}}}" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = c_ret_struct_u32_union_u32_u32u32(); try expect(s.a == 1); @@ -16453,7 +16366,6 @@ test "struct i32 i32" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s: Struct_i32_i32 = .{ @@ -16487,7 +16399,6 @@ test "big struct" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16516,7 +16427,6 @@ test "big union" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -16552,7 +16462,6 @@ test "medium struct of ints and floats" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = MedStructMixed{ .a = 1234, @@ -16633,7 +16542,6 @@ test "split struct of ints" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = SplitStructInt{ .a = 1234, @@ -16663,7 +16571,6 @@ test "split struct of ints and floats" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = SplitStructMixed{ .a = 1234, @@ -16690,7 +16597,6 @@ test "sret and byval together" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16805,7 +16711,6 @@ test "Struct with array as padding." { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 }); @@ -16833,7 +16738,6 @@ test "Float array like struct" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; c_float_array_struct(.{ .origin = .{ @@ -16869,7 +16773,6 @@ test "DC: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 })); } test "DC: Zig returns to C" { @@ -16877,7 +16780,6 @@ test "DC: Zig returns to C" { if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_DC()); } test "DC: C passes to Zig" { @@ -16886,7 +16788,6 @@ test "DC: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_send_DC()); } test "DC: C returns to Zig" { @@ -16894,7 +16795,6 @@ test "DC: C returns to Zig" { if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC()); } @@ -16922,14 +16822,12 @@ test "CFF: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 })); } test "CFF: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_CFF()); } test "CFF: C passes to Zig" { @@ -16939,7 +16837,6 @@ test "CFF: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_send_CFF()); } @@ -16948,7 +16845,6 @@ test "CFF: C returns to Zig" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF()); } pub extern fn c_assert_CFF(lv: CFF) c_int; @@ -16975,7 +16871,6 @@ test "PD: Zig passes to C" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 })); } @@ -16983,7 +16878,6 @@ test "PD: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectOk(c_assert_ret_PD()); } test "PD: C passes to Zig" { @@ -16991,7 +16885,6 @@ test "PD: C passes to Zig" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; try expectOk(c_send_PD()); } @@ -16999,7 +16892,6 @@ test "PD: C returns to Zig" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD()); } pub extern fn c_assert_PD(lv: PD) c_int; @@ -17033,7 +16925,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef; test "C function modifies by ref param" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined }); try expect(res.val == 42); @@ -17058,7 +16949,6 @@ test "C function that takes byval struct called via function pointer" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; var fn_ptr = &c_func_ptr_byval; _ = &fn_ptr; @@ -17211,7 +17101,6 @@ test "Stdcall ABI structs" { if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const res = stdcall_coord2( @@ -17228,7 +17117,6 @@ test "Stdcall ABI big union" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -17304,7 +17192,6 @@ test "byval tail callsite attribute" { if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // Originally reported at https://github.com/ziglang/zig/issues/16290 // the bug was that the extern function had the byval attribute, but -- 2.54.0 From a242b0be888fbcffd4eaa2e3af9cb30bc3c71584 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 19:25:35 -0400 Subject: [PATCH 049/215] compiler_rt: change float abi so it can become compatible with cbe --- lib/compiler/resinator/parse.zig | 2 +- lib/compiler_rt.zig | 292 ++- lib/compiler_rt/absv.zig | 3 +- lib/compiler_rt/absvdi2.zig | 5 +- lib/compiler_rt/absvsi2.zig | 2 +- lib/compiler_rt/absvti2.zig | 5 +- lib/compiler_rt/adddf3.zig | 19 - lib/compiler_rt/addf3.zig | 133 +- lib/compiler_rt/addf3_test.zig | 13 +- lib/compiler_rt/addhf3.zig | 11 - lib/compiler_rt/addsf3.zig | 19 - lib/compiler_rt/addtf3.zig | 22 - lib/compiler_rt/addvdi3.zig | 5 +- lib/compiler_rt/addvsi3.zig | 2 +- lib/compiler_rt/addxf3.zig | 11 - lib/compiler_rt/atomics.zig | 2 +- lib/compiler_rt/aulldiv.zig | 2 +- lib/compiler_rt/cmpdf2.zig | 67 - lib/compiler_rt/cmptf2.zig | 146 -- lib/compiler_rt/cmpxf2.zig | 49 - lib/compiler_rt/comparedf2_test.zig | 90 +- lib/compiler_rt/comparef.zig | 449 +++-- lib/compiler_rt/comparesf2_test.zig | 90 +- lib/compiler_rt/cos.zig | 114 +- lib/compiler_rt/count0bits.zig | 3 +- lib/compiler_rt/divc3.zig | 83 +- lib/compiler_rt/divc3_test.zig | 79 +- lib/compiler_rt/divdc3.zig | 13 - lib/compiler_rt/divdf3.zig | 8 +- lib/compiler_rt/divdf3_test.zig | 4 +- lib/compiler_rt/divhc3.zig | 14 - lib/compiler_rt/divhf3.zig | 11 - lib/compiler_rt/divmodei4.zig | 2 +- lib/compiler_rt/divsc3.zig | 13 - lib/compiler_rt/divsf3.zig | 17 +- lib/compiler_rt/divsf3_test.zig | 4 +- lib/compiler_rt/divtc3.zig | 16 - lib/compiler_rt/divtf3.zig | 11 +- lib/compiler_rt/divtf3_test.zig | 4 +- lib/compiler_rt/divxc3.zig | 13 - lib/compiler_rt/divxf3.zig | 5 +- lib/compiler_rt/divxf3_test.zig | 6 +- lib/compiler_rt/exp.zig | 194 +- lib/compiler_rt/exp2.zig | 153 +- lib/compiler_rt/exp_f128.zig | 4 +- lib/compiler_rt/extenddftf2.zig | 22 - lib/compiler_rt/extenddfxf2.zig | 11 - lib/compiler_rt/extendf.zig | 181 +- lib/compiler_rt/extendf_test.zig | 189 +- lib/compiler_rt/extendhfdf2.zig | 11 - lib/compiler_rt/extendhfsf2.zig | 24 - lib/compiler_rt/extendhftf2.zig | 11 - lib/compiler_rt/extendhfxf2.zig | 11 - lib/compiler_rt/extendsfdf2.zig | 19 - lib/compiler_rt/extendsftf2.zig | 22 - lib/compiler_rt/extendsfxf2.zig | 10 - lib/compiler_rt/extendxftf2.zig | 42 - lib/compiler_rt/fabs.zig | 33 +- lib/compiler_rt/fixdfdi.zig | 23 - lib/compiler_rt/fixdfei.zig | 14 - lib/compiler_rt/fixdfsi.zig | 19 - lib/compiler_rt/fixdfti.zig | 11 - lib/compiler_rt/fixhfei.zig | 14 - lib/compiler_rt/fixint_test.zig | 149 -- lib/compiler_rt/fixsfdi.zig | 23 - lib/compiler_rt/fixsfei.zig | 14 - lib/compiler_rt/fixsfsi.zig | 19 - lib/compiler_rt/fixsfti.zig | 12 - lib/compiler_rt/fixtfdi.zig | 22 - lib/compiler_rt/fixtfei.zig | 14 - lib/compiler_rt/fixtfsi.zig | 22 - lib/compiler_rt/fixtfti.zig | 13 - lib/compiler_rt/fixunsdfdi.zig | 23 - lib/compiler_rt/fixunsdfei.zig | 15 - lib/compiler_rt/fixunsdfsi.zig | 19 - lib/compiler_rt/fixunsdfti.zig | 11 - lib/compiler_rt/fixunshfdi.zig | 10 - lib/compiler_rt/fixunshfei.zig | 15 - lib/compiler_rt/fixunshfsi.zig | 11 - lib/compiler_rt/fixunshfti.zig | 11 - lib/compiler_rt/fixunssfdi.zig | 23 - lib/compiler_rt/fixunssfei.zig | 15 - lib/compiler_rt/fixunssfsi.zig | 19 - lib/compiler_rt/fixunssfti.zig | 12 - lib/compiler_rt/fixunstfdi.zig | 22 - lib/compiler_rt/fixunstfei.zig | 15 - lib/compiler_rt/fixunstfsi.zig | 22 - lib/compiler_rt/fixunstfti.zig | 14 - lib/compiler_rt/fixunsxfdi.zig | 10 - lib/compiler_rt/fixunsxfei.zig | 13 - lib/compiler_rt/fixunsxfsi.zig | 11 - lib/compiler_rt/fixunsxfti.zig | 12 - lib/compiler_rt/fixxfdi.zig | 10 - lib/compiler_rt/fixxfei.zig | 14 - lib/compiler_rt/fixxfsi.zig | 11 - lib/compiler_rt/float_from_int.zig | 476 ++++- lib/compiler_rt/float_from_int_test.zig | 1424 +++++++-------- lib/compiler_rt/floatdidf.zig | 23 - lib/compiler_rt/floatdihf.zig | 10 - lib/compiler_rt/floatdisf.zig | 22 - lib/compiler_rt/floatditf.zig | 22 - lib/compiler_rt/floatdixf.zig | 10 - lib/compiler_rt/floateidf.zig | 15 - lib/compiler_rt/floateihf.zig | 14 - lib/compiler_rt/floateisf.zig | 14 - lib/compiler_rt/floateitf.zig | 14 - lib/compiler_rt/floateixf.zig | 15 - lib/compiler_rt/floatsidf.zig | 19 - lib/compiler_rt/floatsihf.zig | 11 - lib/compiler_rt/floatsisf.zig | 19 - lib/compiler_rt/floatsitf.zig | 22 - lib/compiler_rt/floatsixf.zig | 11 - lib/compiler_rt/floattidf.zig | 11 - lib/compiler_rt/floattihf.zig | 12 - lib/compiler_rt/floattisf.zig | 11 - lib/compiler_rt/floattitf.zig | 13 - lib/compiler_rt/floattixf.zig | 12 - lib/compiler_rt/floatundidf.zig | 22 - lib/compiler_rt/floatundihf.zig | 11 - lib/compiler_rt/floatundisf.zig | 23 - lib/compiler_rt/floatunditf.zig | 22 - lib/compiler_rt/floatundixf.zig | 11 - lib/compiler_rt/floatuneidf.zig | 14 - lib/compiler_rt/floatuneihf.zig | 14 - lib/compiler_rt/floatuneisf.zig | 14 - lib/compiler_rt/floatuneitf.zig | 15 - lib/compiler_rt/floatuneixf.zig | 14 - lib/compiler_rt/floatunsidf.zig | 19 - lib/compiler_rt/floatunsihf.zig | 10 - lib/compiler_rt/floatunsisf.zig | 19 - lib/compiler_rt/floatunsitf.zig | 22 - lib/compiler_rt/floatunsixf.zig | 11 - lib/compiler_rt/floatuntidf.zig | 11 - lib/compiler_rt/floatuntihf.zig | 11 - lib/compiler_rt/floatuntisf.zig | 12 - lib/compiler_rt/floatuntitf.zig | 13 - lib/compiler_rt/floatuntixf.zig | 12 - lib/compiler_rt/floor_ceil.zig | 322 ++-- lib/compiler_rt/fma.zig | 79 +- lib/compiler_rt/fmax.zig | 33 +- lib/compiler_rt/fmin.zig | 33 +- lib/compiler_rt/fmod.zig | 83 +- lib/compiler_rt/fmodq_test.zig | 64 +- lib/compiler_rt/fmodx_test.zig | 62 +- lib/compiler_rt/gedf2.zig | 35 - lib/compiler_rt/gehf2.zig | 21 - lib/compiler_rt/gesf2.zig | 35 - lib/compiler_rt/getf2.zig | 26 - lib/compiler_rt/gexf2.zig | 15 - lib/compiler_rt/int.zig | 79 +- lib/compiler_rt/int_from_float.zig | 522 +++++- lib/compiler_rt/int_from_float_test.zig | 1878 ++++++++++---------- lib/compiler_rt/limb64.zig | 2 +- lib/compiler_rt/log.zig | 209 ++- lib/compiler_rt/log10.zig | 211 ++- lib/compiler_rt/log2.zig | 195 +- lib/compiler_rt/mulc3.zig | 85 +- lib/compiler_rt/mulc3_test.zig | 65 +- lib/compiler_rt/muldc3.zig | 12 - lib/compiler_rt/muldf3.zig | 19 - lib/compiler_rt/mulf3.zig | 68 +- lib/compiler_rt/mulf3_test.zig | 90 +- lib/compiler_rt/mulhc3.zig | 13 - lib/compiler_rt/mulhf3.zig | 11 - lib/compiler_rt/mulsc3.zig | 12 - lib/compiler_rt/mulsf3.zig | 19 - lib/compiler_rt/multc3.zig | 15 - lib/compiler_rt/multf3.zig | 22 - lib/compiler_rt/mulvsi3.zig | 5 +- lib/compiler_rt/mulxc3.zig | 13 - lib/compiler_rt/mulxf3.zig | 11 - lib/compiler_rt/negv.zig | 3 +- lib/compiler_rt/os_version_check.zig | 1 - lib/compiler_rt/parity.zig | 3 +- lib/compiler_rt/popcount.zig | 3 +- lib/compiler_rt/powiXf2.zig | 39 +- lib/compiler_rt/powiXf2_test.zig | 1008 +++++------ lib/compiler_rt/round.zig | 136 +- lib/compiler_rt/sin.zig | 114 +- lib/compiler_rt/sincos.zig | 301 ++-- lib/compiler_rt/sqrt.zig | 281 +-- lib/compiler_rt/subdf3.zig | 24 - lib/compiler_rt/subhf3.zig | 12 - lib/compiler_rt/subsf3.zig | 24 - lib/compiler_rt/subtf3.zig | 27 - lib/compiler_rt/subvdi3.zig | 5 +- lib/compiler_rt/subvsi3.zig | 2 +- lib/compiler_rt/subxf3.zig | 13 - lib/compiler_rt/tan.zig | 85 +- lib/compiler_rt/trunc.zig | 119 +- lib/compiler_rt/truncdfhf2.zig | 18 - lib/compiler_rt/truncdfsf2.zig | 19 - lib/compiler_rt/truncf.zig | 202 ++- lib/compiler_rt/truncf_test.zig | 334 ++-- lib/compiler_rt/truncsfhf2.zig | 24 - lib/compiler_rt/trunctfdf2.zig | 22 - lib/compiler_rt/trunctfhf2.zig | 14 - lib/compiler_rt/trunctfsf2.zig | 22 - lib/compiler_rt/trunctfxf2.zig | 67 - lib/compiler_rt/truncxfdf2.zig | 10 - lib/compiler_rt/truncxfhf2.zig | 11 - lib/compiler_rt/truncxfsf2.zig | 10 - lib/compiler_rt/udivmodei4.zig | 2 +- lib/compiler_rt/unorddf2.zig | 19 - lib/std/crypto/Certificate.zig | 2 +- lib/std/math.zig | 4 +- lib/std/math/atan2.zig | 8 +- lib/std/zig/target.zig | 14 + src/link.zig | 2 +- test/behavior/cast.zig | 2 +- test/behavior/floatop.zig | 8 +- test/behavior/switch.zig | 2 +- test/behavior/switch_on_captured_error.zig | 6 +- 213 files changed, 6385 insertions(+), 7004 deletions(-) delete mode 100644 lib/compiler_rt/adddf3.zig delete mode 100644 lib/compiler_rt/addhf3.zig delete mode 100644 lib/compiler_rt/addsf3.zig delete mode 100644 lib/compiler_rt/addtf3.zig delete mode 100644 lib/compiler_rt/addxf3.zig delete mode 100644 lib/compiler_rt/cmpdf2.zig delete mode 100644 lib/compiler_rt/cmptf2.zig delete mode 100644 lib/compiler_rt/cmpxf2.zig delete mode 100644 lib/compiler_rt/divdc3.zig delete mode 100644 lib/compiler_rt/divhc3.zig delete mode 100644 lib/compiler_rt/divhf3.zig delete mode 100644 lib/compiler_rt/divsc3.zig delete mode 100644 lib/compiler_rt/divtc3.zig delete mode 100644 lib/compiler_rt/divxc3.zig delete mode 100644 lib/compiler_rt/extenddftf2.zig delete mode 100644 lib/compiler_rt/extenddfxf2.zig delete mode 100644 lib/compiler_rt/extendhfdf2.zig delete mode 100644 lib/compiler_rt/extendhfsf2.zig delete mode 100644 lib/compiler_rt/extendhftf2.zig delete mode 100644 lib/compiler_rt/extendhfxf2.zig delete mode 100644 lib/compiler_rt/extendsfdf2.zig delete mode 100644 lib/compiler_rt/extendsftf2.zig delete mode 100644 lib/compiler_rt/extendsfxf2.zig delete mode 100644 lib/compiler_rt/extendxftf2.zig delete mode 100644 lib/compiler_rt/fixdfdi.zig delete mode 100644 lib/compiler_rt/fixdfei.zig delete mode 100644 lib/compiler_rt/fixdfsi.zig delete mode 100644 lib/compiler_rt/fixdfti.zig delete mode 100644 lib/compiler_rt/fixhfei.zig delete mode 100644 lib/compiler_rt/fixint_test.zig delete mode 100644 lib/compiler_rt/fixsfdi.zig delete mode 100644 lib/compiler_rt/fixsfei.zig delete mode 100644 lib/compiler_rt/fixsfsi.zig delete mode 100644 lib/compiler_rt/fixsfti.zig delete mode 100644 lib/compiler_rt/fixtfdi.zig delete mode 100644 lib/compiler_rt/fixtfei.zig delete mode 100644 lib/compiler_rt/fixtfsi.zig delete mode 100644 lib/compiler_rt/fixtfti.zig delete mode 100644 lib/compiler_rt/fixunsdfdi.zig delete mode 100644 lib/compiler_rt/fixunsdfei.zig delete mode 100644 lib/compiler_rt/fixunsdfsi.zig delete mode 100644 lib/compiler_rt/fixunsdfti.zig delete mode 100644 lib/compiler_rt/fixunshfdi.zig delete mode 100644 lib/compiler_rt/fixunshfei.zig delete mode 100644 lib/compiler_rt/fixunshfsi.zig delete mode 100644 lib/compiler_rt/fixunshfti.zig delete mode 100644 lib/compiler_rt/fixunssfdi.zig delete mode 100644 lib/compiler_rt/fixunssfei.zig delete mode 100644 lib/compiler_rt/fixunssfsi.zig delete mode 100644 lib/compiler_rt/fixunssfti.zig delete mode 100644 lib/compiler_rt/fixunstfdi.zig delete mode 100644 lib/compiler_rt/fixunstfei.zig delete mode 100644 lib/compiler_rt/fixunstfsi.zig delete mode 100644 lib/compiler_rt/fixunstfti.zig delete mode 100644 lib/compiler_rt/fixunsxfdi.zig delete mode 100644 lib/compiler_rt/fixunsxfei.zig delete mode 100644 lib/compiler_rt/fixunsxfsi.zig delete mode 100644 lib/compiler_rt/fixunsxfti.zig delete mode 100644 lib/compiler_rt/fixxfdi.zig delete mode 100644 lib/compiler_rt/fixxfei.zig delete mode 100644 lib/compiler_rt/fixxfsi.zig delete mode 100644 lib/compiler_rt/floatdidf.zig delete mode 100644 lib/compiler_rt/floatdihf.zig delete mode 100644 lib/compiler_rt/floatdisf.zig delete mode 100644 lib/compiler_rt/floatditf.zig delete mode 100644 lib/compiler_rt/floatdixf.zig delete mode 100644 lib/compiler_rt/floateidf.zig delete mode 100644 lib/compiler_rt/floateihf.zig delete mode 100644 lib/compiler_rt/floateisf.zig delete mode 100644 lib/compiler_rt/floateitf.zig delete mode 100644 lib/compiler_rt/floateixf.zig delete mode 100644 lib/compiler_rt/floatsidf.zig delete mode 100644 lib/compiler_rt/floatsihf.zig delete mode 100644 lib/compiler_rt/floatsisf.zig delete mode 100644 lib/compiler_rt/floatsitf.zig delete mode 100644 lib/compiler_rt/floatsixf.zig delete mode 100644 lib/compiler_rt/floattidf.zig delete mode 100644 lib/compiler_rt/floattihf.zig delete mode 100644 lib/compiler_rt/floattisf.zig delete mode 100644 lib/compiler_rt/floattitf.zig delete mode 100644 lib/compiler_rt/floattixf.zig delete mode 100644 lib/compiler_rt/floatundidf.zig delete mode 100644 lib/compiler_rt/floatundihf.zig delete mode 100644 lib/compiler_rt/floatundisf.zig delete mode 100644 lib/compiler_rt/floatunditf.zig delete mode 100644 lib/compiler_rt/floatundixf.zig delete mode 100644 lib/compiler_rt/floatuneidf.zig delete mode 100644 lib/compiler_rt/floatuneihf.zig delete mode 100644 lib/compiler_rt/floatuneisf.zig delete mode 100644 lib/compiler_rt/floatuneitf.zig delete mode 100644 lib/compiler_rt/floatuneixf.zig delete mode 100644 lib/compiler_rt/floatunsidf.zig delete mode 100644 lib/compiler_rt/floatunsihf.zig delete mode 100644 lib/compiler_rt/floatunsisf.zig delete mode 100644 lib/compiler_rt/floatunsitf.zig delete mode 100644 lib/compiler_rt/floatunsixf.zig delete mode 100644 lib/compiler_rt/floatuntidf.zig delete mode 100644 lib/compiler_rt/floatuntihf.zig delete mode 100644 lib/compiler_rt/floatuntisf.zig delete mode 100644 lib/compiler_rt/floatuntitf.zig delete mode 100644 lib/compiler_rt/floatuntixf.zig delete mode 100644 lib/compiler_rt/gedf2.zig delete mode 100644 lib/compiler_rt/gehf2.zig delete mode 100644 lib/compiler_rt/gesf2.zig delete mode 100644 lib/compiler_rt/getf2.zig delete mode 100644 lib/compiler_rt/gexf2.zig delete mode 100644 lib/compiler_rt/muldc3.zig delete mode 100644 lib/compiler_rt/muldf3.zig delete mode 100644 lib/compiler_rt/mulhc3.zig delete mode 100644 lib/compiler_rt/mulhf3.zig delete mode 100644 lib/compiler_rt/mulsc3.zig delete mode 100644 lib/compiler_rt/mulsf3.zig delete mode 100644 lib/compiler_rt/multc3.zig delete mode 100644 lib/compiler_rt/multf3.zig delete mode 100644 lib/compiler_rt/mulxc3.zig delete mode 100644 lib/compiler_rt/mulxf3.zig delete mode 100644 lib/compiler_rt/subdf3.zig delete mode 100644 lib/compiler_rt/subhf3.zig delete mode 100644 lib/compiler_rt/subsf3.zig delete mode 100644 lib/compiler_rt/subtf3.zig delete mode 100644 lib/compiler_rt/subxf3.zig delete mode 100644 lib/compiler_rt/truncdfhf2.zig delete mode 100644 lib/compiler_rt/truncdfsf2.zig delete mode 100644 lib/compiler_rt/truncsfhf2.zig delete mode 100644 lib/compiler_rt/trunctfdf2.zig delete mode 100644 lib/compiler_rt/trunctfhf2.zig delete mode 100644 lib/compiler_rt/trunctfsf2.zig delete mode 100644 lib/compiler_rt/trunctfxf2.zig delete mode 100644 lib/compiler_rt/truncxfdf2.zig delete mode 100644 lib/compiler_rt/truncxfhf2.zig delete mode 100644 lib/compiler_rt/truncxfsf2.zig delete mode 100644 lib/compiler_rt/unorddf2.zig diff --git a/lib/compiler/resinator/parse.zig b/lib/compiler/resinator/parse.zig index 445424429ea2249991661e99840331e2b936bd96..1f3b2f156ae15fb7fb548ffe37bce6f036079e19 100644 --- a/lib/compiler/resinator/parse.zig +++ b/lib/compiler/resinator/parse.zig @@ -1277,7 +1277,7 @@ pub const Parser = struct { }, else => unreachable, } - @compileError("unreachable"); + comptime unreachable; } pub const OptionalParamParser = struct { diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index f042d0076e62740c50d61b4e28b8b3ddb07012f3..5ff6e659d56f0797225b7661aa076cb41f715a42 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -1,4 +1,5 @@ const builtin = @import("builtin"); +const compiler_rt = @This(); const ofmt_c = builtin.object_format == .c; const native_endian = builtin.cpu.arch.endian(); @@ -84,144 +85,17 @@ comptime { // Float routines // conversion _ = @import("compiler_rt/extendf.zig"); - _ = @import("compiler_rt/extendhfsf2.zig"); - _ = @import("compiler_rt/extendhfdf2.zig"); - _ = @import("compiler_rt/extendhftf2.zig"); - _ = @import("compiler_rt/extendhfxf2.zig"); - _ = @import("compiler_rt/extendsfdf2.zig"); - _ = @import("compiler_rt/extendsftf2.zig"); - _ = @import("compiler_rt/extendsfxf2.zig"); - _ = @import("compiler_rt/extenddftf2.zig"); - _ = @import("compiler_rt/extenddfxf2.zig"); - _ = @import("compiler_rt/extendxftf2.zig"); - _ = @import("compiler_rt/truncf.zig"); - _ = @import("compiler_rt/truncsfhf2.zig"); - _ = @import("compiler_rt/truncdfhf2.zig"); - _ = @import("compiler_rt/truncdfsf2.zig"); - _ = @import("compiler_rt/truncxfhf2.zig"); - _ = @import("compiler_rt/truncxfsf2.zig"); - _ = @import("compiler_rt/truncxfdf2.zig"); - _ = @import("compiler_rt/trunctfhf2.zig"); - _ = @import("compiler_rt/trunctfsf2.zig"); - _ = @import("compiler_rt/trunctfdf2.zig"); - _ = @import("compiler_rt/trunctfxf2.zig"); - _ = @import("compiler_rt/int_from_float.zig"); - _ = @import("compiler_rt/fixhfei.zig"); - _ = @import("compiler_rt/fixsfsi.zig"); - _ = @import("compiler_rt/fixsfdi.zig"); - _ = @import("compiler_rt/fixsfti.zig"); - _ = @import("compiler_rt/fixsfei.zig"); - _ = @import("compiler_rt/fixdfsi.zig"); - _ = @import("compiler_rt/fixdfdi.zig"); - _ = @import("compiler_rt/fixdfti.zig"); - _ = @import("compiler_rt/fixdfei.zig"); - _ = @import("compiler_rt/fixtfsi.zig"); - _ = @import("compiler_rt/fixtfdi.zig"); - _ = @import("compiler_rt/fixtfti.zig"); - _ = @import("compiler_rt/fixtfei.zig"); - _ = @import("compiler_rt/fixxfsi.zig"); - _ = @import("compiler_rt/fixxfdi.zig"); - _ = @import("compiler_rt/fixxfei.zig"); - - _ = @import("compiler_rt/fixunshfsi.zig"); - _ = @import("compiler_rt/fixunshfdi.zig"); - _ = @import("compiler_rt/fixunshfti.zig"); - _ = @import("compiler_rt/fixunshfei.zig"); - _ = @import("compiler_rt/fixunssfsi.zig"); - _ = @import("compiler_rt/fixunssfdi.zig"); - _ = @import("compiler_rt/fixunssfti.zig"); - _ = @import("compiler_rt/fixunssfei.zig"); - _ = @import("compiler_rt/fixunsdfsi.zig"); - _ = @import("compiler_rt/fixunsdfdi.zig"); - _ = @import("compiler_rt/fixunsdfti.zig"); - _ = @import("compiler_rt/fixunsdfei.zig"); - _ = @import("compiler_rt/fixunstfsi.zig"); - _ = @import("compiler_rt/fixunstfdi.zig"); - _ = @import("compiler_rt/fixunstfti.zig"); - _ = @import("compiler_rt/fixunstfei.zig"); - _ = @import("compiler_rt/fixunsxfsi.zig"); - _ = @import("compiler_rt/fixunsxfdi.zig"); - _ = @import("compiler_rt/fixunsxfti.zig"); - _ = @import("compiler_rt/fixunsxfei.zig"); - _ = @import("compiler_rt/float_from_int.zig"); - _ = @import("compiler_rt/floatsihf.zig"); - _ = @import("compiler_rt/floatsisf.zig"); - _ = @import("compiler_rt/floatsidf.zig"); - _ = @import("compiler_rt/floatsitf.zig"); - _ = @import("compiler_rt/floatsixf.zig"); - _ = @import("compiler_rt/floatdihf.zig"); - _ = @import("compiler_rt/floatdisf.zig"); - _ = @import("compiler_rt/floatdidf.zig"); - _ = @import("compiler_rt/floatditf.zig"); - _ = @import("compiler_rt/floatdixf.zig"); - _ = @import("compiler_rt/floattihf.zig"); - _ = @import("compiler_rt/floattisf.zig"); - _ = @import("compiler_rt/floattidf.zig"); - _ = @import("compiler_rt/floattitf.zig"); - _ = @import("compiler_rt/floattixf.zig"); - _ = @import("compiler_rt/floateihf.zig"); - _ = @import("compiler_rt/floateisf.zig"); - _ = @import("compiler_rt/floateidf.zig"); - _ = @import("compiler_rt/floateitf.zig"); - _ = @import("compiler_rt/floateixf.zig"); - _ = @import("compiler_rt/floatunsihf.zig"); - _ = @import("compiler_rt/floatunsisf.zig"); - _ = @import("compiler_rt/floatunsidf.zig"); - _ = @import("compiler_rt/floatunsitf.zig"); - _ = @import("compiler_rt/floatunsixf.zig"); - _ = @import("compiler_rt/floatundihf.zig"); - _ = @import("compiler_rt/floatundisf.zig"); - _ = @import("compiler_rt/floatundidf.zig"); - _ = @import("compiler_rt/floatunditf.zig"); - _ = @import("compiler_rt/floatundixf.zig"); - _ = @import("compiler_rt/floatuntihf.zig"); - _ = @import("compiler_rt/floatuntisf.zig"); - _ = @import("compiler_rt/floatuntidf.zig"); - _ = @import("compiler_rt/floatuntitf.zig"); - _ = @import("compiler_rt/floatuntixf.zig"); - _ = @import("compiler_rt/floatuneihf.zig"); - _ = @import("compiler_rt/floatuneisf.zig"); - _ = @import("compiler_rt/floatuneidf.zig"); - _ = @import("compiler_rt/floatuneitf.zig"); - _ = @import("compiler_rt/floatuneixf.zig"); // comparison _ = @import("compiler_rt/comparef.zig"); - _ = @import("compiler_rt/cmpdf2.zig"); - _ = @import("compiler_rt/cmptf2.zig"); - _ = @import("compiler_rt/cmpxf2.zig"); - _ = @import("compiler_rt/unorddf2.zig"); - _ = @import("compiler_rt/gehf2.zig"); - _ = @import("compiler_rt/gesf2.zig"); - _ = @import("compiler_rt/gedf2.zig"); - _ = @import("compiler_rt/gexf2.zig"); - _ = @import("compiler_rt/getf2.zig"); // arithmetic _ = @import("compiler_rt/addf3.zig"); - _ = @import("compiler_rt/addhf3.zig"); - _ = @import("compiler_rt/addsf3.zig"); - _ = @import("compiler_rt/adddf3.zig"); - _ = @import("compiler_rt/addtf3.zig"); - _ = @import("compiler_rt/addxf3.zig"); - - _ = @import("compiler_rt/subhf3.zig"); - _ = @import("compiler_rt/subsf3.zig"); - _ = @import("compiler_rt/subdf3.zig"); - _ = @import("compiler_rt/subtf3.zig"); - _ = @import("compiler_rt/subxf3.zig"); - _ = @import("compiler_rt/mulf3.zig"); - _ = @import("compiler_rt/mulhf3.zig"); - _ = @import("compiler_rt/mulsf3.zig"); - _ = @import("compiler_rt/muldf3.zig"); - _ = @import("compiler_rt/multf3.zig"); - _ = @import("compiler_rt/mulxf3.zig"); - _ = @import("compiler_rt/divhf3.zig"); _ = @import("compiler_rt/divsf3.zig"); _ = @import("compiler_rt/divdf3.zig"); _ = @import("compiler_rt/divxf3.zig"); @@ -235,25 +109,17 @@ comptime { symbol(&__negsf2, "__negsf2"); symbol(&__negdf2, "__negdf2"); } - if (want_ppc_abi) symbol(&__negtf2, "__negkf2"); - symbol(&__negtf2, "__negtf2"); + if (want_ppc_abi) { + symbol(&__negtf2, "__negkf2"); + } else { + symbol(&__negtf2, "__negtf2"); + } symbol(&__negxf2, "__negxf2"); // other _ = @import("compiler_rt/powiXf2.zig"); _ = @import("compiler_rt/mulc3.zig"); - _ = @import("compiler_rt/mulhc3.zig"); - _ = @import("compiler_rt/mulsc3.zig"); - _ = @import("compiler_rt/muldc3.zig"); - _ = @import("compiler_rt/mulxc3.zig"); - _ = @import("compiler_rt/multc3.zig"); - _ = @import("compiler_rt/divc3.zig"); - _ = @import("compiler_rt/divhc3.zig"); - _ = @import("compiler_rt/divsc3.zig"); - _ = @import("compiler_rt/divdc3.zig"); - _ = @import("compiler_rt/divxc3.zig"); - _ = @import("compiler_rt/divtc3.zig"); // Math routines. Alphabetically sorted. _ = @import("compiler_rt/cos.zig"); @@ -279,7 +145,7 @@ comptime { _ = @import("compiler_rt/divmodei4.zig"); _ = @import("compiler_rt/udivmodei4.zig"); - _ = @import("compiler_rt/limb64.zig"); + if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig"); // extra _ = @import("compiler_rt/os_version_check.zig"); @@ -290,7 +156,7 @@ comptime { _ = @import("compiler_rt/clear_cache.zig"); _ = @import("compiler_rt/hexagon.zig"); - if (@import("builtin").object_format != .c) { + if (builtin.object_format != .c) { if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig"); _ = @import("compiler_rt/stack_probe.zig"); @@ -366,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) { .gnueabihf, .android, .androideabi, - => switch (builtin.cpu.arch) { - .arm, .armeb, .thumb, .thumbeb => true, - else => false, - }, + => builtin.cpu.arch.isArm(), else => false, }; @@ -443,17 +306,106 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) { pub const want_sparc64_abi = builtin.cpu.arch == .sparc64; pub const want_sparc32_abi = builtin.cpu.arch == .sparc; -pub fn F16T(comptime OtherType: type) type { - return switch (builtin.cpu.arch) { - .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) { - // Starting with LLVM 16, Darwin uses different abi for f16 - // depending on the type of the other return/argument..??? - f32, f64 => u16, - f80, f128 => f16, - else => unreachable, - } else f16, - else => f16, +/// For operations converting between `f16` and another floating point type. +pub fn f16Conv(comptime OtherType: type) type { + switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { + .hard => {}, + .soft => return softFloatAbi(f16), + } + if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) { + else => unreachable, + // Starting with LLVM 16, Darwin uses different abi for f16 + // depending on the type of the other return/argument..??? + f32, f64 => return softFloatAbi(f16), + f80, f128 => {}, }; + return hardFloatAbi(f16); +} +pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { + .hard => hardFloatAbi(f16), + .soft => softFloatAbi(f16), +}; +pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) { + .hard => hardFloatAbi(f32), + .soft => softFloatAbi(f32), +}; +pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) { + .hard => hardFloatAbi(f64), + .soft => softFloatAbi(f64), +}; +pub const @"f80" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 80)) { + .hard => hardFloatAbi(f80), + .soft => struct { + pub const Abi = extern struct { mantissa: u64, exponent: u16 }; + const Repr = packed struct { mantissa: u64, exponent: u16 }; + pub inline fn toAbi(raw: f80) Abi { + const repr: Repr = @bitCast(raw); + return .{ .mantissa = repr.mantissa, .exponent = repr.exponent }; + } + pub inline fn fromAbi(abi: Abi) f80 { + const repr: Repr = .{ .mantissa = abi.mantissa, .exponent = abi.exponent }; + return @bitCast(repr); + } + pub const complex = complexAbi(f80, @This()); + }, +}; +pub const @"f128" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 128)) { + .hard => hardFloatAbi(f128), + .soft => struct { + pub const Abi = switch (builtin.cpu.arch.endian()) { + .big => extern struct { hi: u64, lo: u64 }, + .little => extern struct { lo: u64, hi: u64 }, + }; + const Repr = packed struct { lo: u64, hi: u64 }; + pub inline fn toAbi(raw: f128) Abi { + const repr: Repr = @bitCast(raw); + return .{ .lo = repr.lo, .hi = repr.hi }; + } + pub inline fn fromAbi(abi: Abi) f128 { + const repr: Repr = .{ .lo = abi.lo, .hi = abi.hi }; + return @bitCast(repr); + } + pub const complex = complexAbi(f128, @This()); + }, +}; +fn hardFloatAbi(comptime Float: type) type { + return struct { + pub const Abi = Float; + pub inline fn toAbi(raw: Float) Abi { + return raw; + } + pub inline fn fromAbi(abi: Abi) Float { + return abi; + } + pub const complex = complexAbi(Float, @This()); + }; +} +fn softFloatAbi(comptime Float: type) type { + return struct { + pub const Abi = @Int(.unsigned, @bitSizeOf(Float)); + pub inline fn toAbi(raw: Float) Abi { + return @bitCast(raw); + } + pub inline fn fromAbi(abi: Abi) Float { + return @bitCast(abi); + } + pub const complex = complexAbi(Float, @This()); + }; +} +fn complexAbi(comptime Float: type, comptime float: type) type { + return struct { + pub const Abi = extern struct { real: float.Abi, imag: float.Abi }; + pub inline fn toAbi(raw: Complex(Float)) Abi { + return .{ .real = float.toAbi(raw.real), .imag = float.toAbi(raw.imag) }; + } + pub inline fn fromAbi(abi: Abi) Complex(Float) { + return .{ .real = float.fromAbi(abi.real), .imag = float.fromAbi(abi.imag) }; + } + }; +} + +pub fn Complex(comptime Float: type) type { + return struct { real: Float, imag: Float }; } pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { @@ -588,34 +540,34 @@ pub inline fn fneg(a: anytype) @TypeOf(a) { return @bitCast(negated); } -fn __negxf2(a: f80) callconv(.c) f80 { - return fneg(a); +fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a))); } -fn __neghf2(a: f16) callconv(.c) f16 { - return fneg(a); +fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a))); } -fn __negdf2(a: f64) callconv(.c) f64 { - return fneg(a); +fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a))); } -fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return fneg(a); +fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a))); } -fn __negtf2(a: f128) callconv(.c) f128 { - return fneg(a); -} - -fn __negsf2(a: f32) callconv(.c) f32 { - return fneg(a); +fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a))); } fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { return fneg(a); } +fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return fneg(a); +} + /// Allows to access underlying bits as two equally sized lower and higher /// signed or unsigned integers. pub fn HalveInt(comptime T: type, comptime signed_half: bool) type { diff --git a/lib/compiler_rt/absv.zig b/lib/compiler_rt/absv.zig index 8910a4a6b9417bd099065db02f1535ace9968ee0..4621835dd6f6abd9cdb37a53231e88139556eb9a 100644 --- a/lib/compiler_rt/absv.zig +++ b/lib/compiler_rt/absv.zig @@ -14,8 +14,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST { const sign: ST = a >> N - 1; x +%= sign; x ^= sign; - if (x < 0) - @panic("compiler_rt absv: overflow"); + if (x < 0) @panic("integer overflow"); return x; } diff --git a/lib/compiler_rt/absvdi2.zig b/lib/compiler_rt/absvdi2.zig index 408d70ad167d29c7895e6145e7635da95ec62a82..598629ebfc689258a055110aa976cf0d3b56226a 100644 --- a/lib/compiler_rt/absvdi2.zig +++ b/lib/compiler_rt/absvdi2.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const absv = @import("./absv.zig").absv; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvdi2, "__absvdi2"); diff --git a/lib/compiler_rt/absvsi2.zig b/lib/compiler_rt/absvsi2.zig index 538d7f7f0155f98cf997b711514145ae77da5c2a..e01627090082800cd53ee4b614f3a68d9480c214 100644 --- a/lib/compiler_rt/absvsi2.zig +++ b/lib/compiler_rt/absvsi2.zig @@ -1,6 +1,6 @@ const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; -const absv = @import("./absv.zig").absv; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvsi2, "__absvsi2"); diff --git a/lib/compiler_rt/absvti2.zig b/lib/compiler_rt/absvti2.zig index ab367d2b78ae2f0a813d011ec74dc532d103303f..008060504e318f7d9979a43d4d53ac34a8d38c76 100644 --- a/lib/compiler_rt/absvti2.zig +++ b/lib/compiler_rt/absvti2.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const absv = @import("./absv.zig").absv; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const absv = @import("absv.zig").absv; comptime { symbol(&__absvti2, "__absvti2"); diff --git a/lib/compiler_rt/adddf3.zig b/lib/compiler_rt/adddf3.zig deleted file mode 100644 index 7b6f252da2c7f697b23b8e9e9fd13d34cc99bc80..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/adddf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dadd, "__aeabi_dadd"); - } else { - symbol(&__adddf3, "__adddf3"); - } -} - -fn __adddf3(a: f64, b: f64) callconv(.c) f64 { - return addf3(f64, a, b); -} - -fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return addf3(f64, a, b); -} diff --git a/lib/compiler_rt/addf3.zig b/lib/compiler_rt/addf3.zig index 1e68c82f0fbcf3a4a28d4d9c0d877b997496d7a2..189f7afd6d02c78bdb63de8e38ca7731c96684d4 100644 --- a/lib/compiler_rt/addf3.zig +++ b/lib/compiler_rt/addf3.zig @@ -1,12 +1,143 @@ const std = @import("std"); const math = std.math; const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; const normalize = compiler_rt.normalize; +comptime { + symbol(&__addhf3, "__addhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fadd, "__aeabi_fadd"); + symbol(&__aeabi_dadd, "__aeabi_dadd"); + } else { + symbol(&__addsf3, "__addsf3"); + symbol(&__adddf3, "__adddf3"); + } + symbol(&__addxf3, "__addxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__addtf3, "__addkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_add, "_Qp_add"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__addtf3, "_Q_add"); + } else { + symbol(&__addtf3, "__addtf3"); + } +} + +fn __addhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(add_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn add_f16(a: f16, b: f16) f16 { + return addf3(f16, a, b); +} + +fn __addsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(add_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return add_f32(a, b); +} +pub fn add_f32(a: f32, b: f32) f32 { + return addf3(f32, a, b); +} + +fn __adddf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(add_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return add_f64(a, b); +} +pub fn add_f64(a: f64, b: f64) f64 { + return addf3(f64, a, b); +} + +fn __addxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(add_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn add_f80(a: f80, b: f80) f80 { + return addf3(f80, a, b); +} + +fn __addtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(add_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void { + c.* = add_f128(a.*, b.*); +} +pub fn add_f128(a: f128, b: f128) f128 { + return addf3(f128, a, b); +} + +comptime { + symbol(&__subhf3, "__subhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fsub, "__aeabi_fsub"); + symbol(&__aeabi_dsub, "__aeabi_dsub"); + } else { + symbol(&__subsf3, "__subsf3"); + symbol(&__subdf3, "__subdf3"); + } + symbol(&__subxf3, "__subxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__subtf3, "__subkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_sub, "_Qp_sub"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__subtf3, "_Q_sub"); + } else { + symbol(&__subtf3, "__subtf3"); + } +} + +fn __subhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sub_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn sub_f16(a: f16, b: f16) f16 { + return add_f16(a, compiler_rt.fneg(b)); +} + +fn __subsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sub_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return sub_f32(a, b); +} +pub fn sub_f32(a: f32, b: f32) f32 { + return add_f32(a, compiler_rt.fneg(b)); +} + +fn __subdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sub_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return sub_f64(a, b); +} +pub fn sub_f64(a: f64, b: f64) f64 { + return add_f64(a, compiler_rt.fneg(b)); +} + +fn __subxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sub_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn sub_f80(a: f80, b: f80) f80 { + return add_f80(a, compiler_rt.fneg(b)); +} + +fn __subtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sub_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { + c.* = sub_f128(a.*, b.*); +} +pub fn sub_f128(a: f128, b: f128) f128 { + return add_f128(a, compiler_rt.fneg(b)); +} + /// Ported from: /// /// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc -pub inline fn addf3(comptime T: type, a: T, b: T) T { +inline fn addf3(comptime T: type, a: T, b: T) T { const bits = @typeInfo(T).float.bits; const Z = @Int(.unsigned, bits); diff --git a/lib/compiler_rt/addf3_test.zig b/lib/compiler_rt/addf3_test.zig index 1e9bfa1bbf5403cee4cb6fc839478782714eca5b..ffa3a48086a47e9617145c0d33e049b221303ec5 100644 --- a/lib/compiler_rt/addf3_test.zig +++ b/lib/compiler_rt/addf3_test.zig @@ -8,12 +8,13 @@ const builtin = @import("builtin"); const math = std.math; const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); -const __addtf3 = @import("addtf3.zig").__addtf3; -const __addxf3 = @import("addxf3.zig").__addxf3; -const __subtf3 = @import("subtf3.zig").__subtf3; +const impl = @import("addf3.zig"); +const add_f128 = impl.add_f128; +const add_f80 = impl.add_f80; +const sub_f128 = impl.sub_f128; fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __addtf3(a, b); + const x = add_f128(a, b); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -52,7 +53,7 @@ test "addtf3" { } fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __subtf3(a, b); + const x = sub_f128(a, b); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -91,7 +92,7 @@ test "subtf3" { const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); fn test__addxf3(a: f80, b: f80, expected: u80) !void { - const x = __addxf3(a, b); + const x = add_f80(a, b); const rep: u80 = @bitCast(x); if (rep == expected) diff --git a/lib/compiler_rt/addhf3.zig b/lib/compiler_rt/addhf3.zig deleted file mode 100644 index bd13f48cac5f1ebeda2f019b1252d6a6967aa964..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__addhf3, "__addhf3"); -} - -fn __addhf3(a: f16, b: f16) callconv(.c) f16 { - return addf3(f16, a, b); -} diff --git a/lib/compiler_rt/addsf3.zig b/lib/compiler_rt/addsf3.zig deleted file mode 100644 index 4878fb704d1769469fb0a9155c930f0e24e0cabc..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addsf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fadd, "__aeabi_fadd"); - } else { - symbol(&__addsf3, "__addsf3"); - } -} - -fn __addsf3(a: f32, b: f32) callconv(.c) f32 { - return addf3(f32, a, b); -} - -fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return addf3(f32, a, b); -} diff --git a/lib/compiler_rt/addtf3.zig b/lib/compiler_rt/addtf3.zig deleted file mode 100644 index 3097027f482ed73deee604acfcd7be877192d1fc..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addtf3.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__addtf3, "__addkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_add, "_Qp_add"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__addtf3, "_Q_add"); - } - symbol(&__addtf3, "__addtf3"); -} - -pub fn __addtf3(a: f128, b: f128) callconv(.c) f128 { - return addf3(f128, a, b); -} - -fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void { - c.* = addf3(f128, a.*, b.*); -} diff --git a/lib/compiler_rt/addvdi3.zig b/lib/compiler_rt/addvdi3.zig index a5cde2494acba14282409395aa47ce9660faa0ff..063c2bcd44f16ea3dcd14fb427b24835830190bd 100644 --- a/lib/compiler_rt/addvdi3.zig +++ b/lib/compiler_rt/addvdi3.zig @@ -1,4 +1,5 @@ -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; const testing = @import("std").testing; comptime { @@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 { const sum = a +% b; // Overflow occurred iff both operands have the same sign, and the sign of the sum does // not match it. In other words, iff the sum sign is not the sign of either operand. - if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow"); + if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/addvsi3.zig b/lib/compiler_rt/addvsi3.zig index c35b22e8dfd73703480c89f4a5d305fa5b8ec9fd..f180f680c52e8ddc4a991838714eff4647cb57ba 100644 --- a/lib/compiler_rt/addvsi3.zig +++ b/lib/compiler_rt/addvsi3.zig @@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 { const sum = a +% b; // Overflow occurred iff both operands have the same sign, and the sign of the sum does // not match it. In other words, iff the sum sign is not the sign of either operand. - if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow"); + if (((sum ^ a) & (sum ^ b)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/addxf3.zig b/lib/compiler_rt/addxf3.zig deleted file mode 100644 index f57708c98553874b47b62591b339e49b22ecedbd..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/addxf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__addxf3, "__addxf3"); -} - -pub fn __addxf3(a: f80, b: f80) callconv(.c) f80 { - return addf3(f80, a, b); -} diff --git a/lib/compiler_rt/atomics.zig b/lib/compiler_rt/atomics.zig index f2c744c730b8c20501af60bf51fa78d57cb7cbc3..83b978a11ca2fad3dc2e4f8483556751c2f6e3d1 100644 --- a/lib/compiler_rt/atomics.zig +++ b/lib/compiler_rt/atomics.zig @@ -5,7 +5,7 @@ const arch = cpu.arch; const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; // This parameter is true iff the target architecture supports the bare minimum // to implement the atomic load/store intrinsics. diff --git a/lib/compiler_rt/aulldiv.zig b/lib/compiler_rt/aulldiv.zig index 4ed92f39eefde1b941634b5b72eac8d1e41ba0d2..3e002379220fa5e957f2d2a728435a2a11972415 100644 --- a/lib/compiler_rt/aulldiv.zig +++ b/lib/compiler_rt/aulldiv.zig @@ -1,7 +1,7 @@ const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { if (compiler_rt.want_windows_x86_msvc_abi) { diff --git a/lib/compiler_rt/cmpdf2.zig b/lib/compiler_rt/cmpdf2.zig deleted file mode 100644 index e55972efbd00da3c3b215e722ba2277557a37525..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmpdf2.zig +++ /dev/null @@ -1,67 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq"); - symbol(&__aeabi_dcmplt, "__aeabi_dcmplt"); - symbol(&__aeabi_dcmple, "__aeabi_dcmple"); - } else { - symbol(&__eqdf2, "__eqdf2"); - symbol(&__nedf2, "__nedf2"); - symbol(&__ledf2, "__ledf2"); - symbol(&__cmpdf2, "__cmpdf2"); - symbol(&__ltdf2, "__ltdf2"); - } -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`, -/// and `__ltdf2`. -fn __cmpdf2(a: f64, b: f64) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f64, comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -pub fn __ledf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined -/// to have the same return value. -pub fn __eqdf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined -/// to have the same return value. -pub fn __nedf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -pub fn __ltdf2(a: f64, b: f64) callconv(.c) i32 { - return __cmpdf2(a, b); -} - -fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal); -} - -fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Less); -} - -fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater); -} diff --git a/lib/compiler_rt/cmptf2.zig b/lib/compiler_rt/cmptf2.zig deleted file mode 100644 index 89418fb320b5b8ea3d2f972cf05dde162eccc7c0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmptf2.zig +++ /dev/null @@ -1,146 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__eqtf2, "__eqkf2"); - symbol(&__netf2, "__nekf2"); - symbol(&__lttf2, "__ltkf2"); - symbol(&__letf2, "__lekf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_cmp, "_Qp_cmp"); - symbol(&_Qp_feq, "_Qp_feq"); - symbol(&_Qp_fne, "_Qp_fne"); - symbol(&_Qp_flt, "_Qp_flt"); - symbol(&_Qp_fle, "_Qp_fle"); - symbol(&_Qp_fgt, "_Qp_fgt"); - symbol(&_Qp_fge, "_Qp_fge"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&_Q_cmp, "_Q_cmp"); - symbol(&_Q_feq, "_Q_feq"); - symbol(&_Q_fne, "_Q_fne"); - symbol(&_Q_flt, "_Q_flt"); - symbol(&_Q_fle, "_Q_fle"); - symbol(&_Q_fgt, "_Q_fgt"); - symbol(&_Q_fge, "_Q_fge"); - } - symbol(&__eqtf2, "__eqtf2"); - symbol(&__netf2, "__netf2"); - symbol(&__letf2, "__letf2"); - symbol(&__cmptf2, "__cmptf2"); - symbol(&__lttf2, "__lttf2"); -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`, -/// and `__lttf2`. -fn __cmptf2(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __letf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined -/// to have the same return value. -fn __eqtf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined -/// to have the same return value. -fn __netf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __lttf2(a: f128, b: f128) callconv(.c) i32 { - return __cmptf2(a, b); -} - -const SparcFCMP = enum(i32) { - Equal = 0, - Less = 1, - Greater = 2, - Unordered = 3, -}; - -fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*)); -} - -fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Equal; -} - -fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) != .Equal; -} - -fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Less; -} - -fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Greater; -} - -fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) { - .Equal, .Greater => true, - .Less, .Unordered => false, - }; -} - -fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b))))) { - .Equal, .Less => true, - .Greater, .Unordered => false, - }; -} - -fn _Q_cmp(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, SparcFCMP, a, b)); -} - -fn _Q_feq(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Equal; -} - -fn _Q_fne(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) != .Equal; -} - -fn _Q_flt(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Less; -} - -fn _Q_fgt(a: f128, b: f128) callconv(.c) bool { - return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Greater; -} - -fn _Q_fge(a: f128, b: f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) { - .Equal, .Greater => true, - .Less, .Unordered => false, - }; -} - -fn _Q_fle(a: f128, b: f128) callconv(.c) bool { - return switch (@as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b))))) { - .Equal, .Less => true, - .Greater, .Unordered => false, - }; -} diff --git a/lib/compiler_rt/cmpxf2.zig b/lib/compiler_rt/cmpxf2.zig deleted file mode 100644 index 8146cd83c2f05bff98a3a122de2431820d897a08..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/cmpxf2.zig +++ /dev/null @@ -1,49 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__eqxf2, "__eqxf2"); - symbol(&__nexf2, "__nexf2"); - symbol(&__lexf2, "__lexf2"); - symbol(&__cmpxf2, "__cmpxf2"); - symbol(&__ltxf2, "__ltxf2"); -} - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`, -/// and `__ltxf2`. -fn __cmpxf2(a: f80, b: f80) callconv(.c) i32 { - return @backingInt(comparef.cmp_f80(comparef.LE, a, b)); -} - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __lexf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined -/// to have the same return value. -fn __eqxf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined -/// to have the same return value. -fn __nexf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __ltxf2(a: f80, b: f80) callconv(.c) i32 { - return __cmpxf2(a, b); -} diff --git a/lib/compiler_rt/comparedf2_test.zig b/lib/compiler_rt/comparedf2_test.zig index dbae6bbeeca09ef401a17334d57f3f3be824c781..cb8a7b727f993f5b57d46e55cfffdafa1343cc78 100644 --- a/lib/compiler_rt/comparedf2_test.zig +++ b/lib/compiler_rt/comparedf2_test.zig @@ -5,52 +5,12 @@ const std = @import("std"); const builtin = @import("builtin"); -const __eqdf2 = @import("./cmpdf2.zig").__eqdf2; -const __ledf2 = @import("./cmpdf2.zig").__ledf2; -const __ltdf2 = @import("./cmpdf2.zig").__ltdf2; -const __nedf2 = @import("./cmpdf2.zig").__nedf2; +const compiler_rt = @import("../compiler_rt.zig"); -const __gedf2 = @import("./gedf2.zig").__gedf2; -const __gtdf2 = @import("./gedf2.zig").__gtdf2; - -const __unorddf2 = @import("./unorddf2.zig").__unorddf2; - -const TestVector = struct { - a: f64, - b: f64, - eqReference: c_int, - geReference: c_int, - gtReference: c_int, - leReference: c_int, - ltReference: c_int, - neReference: c_int, - unReference: c_int, -}; - -fn test__cmpdf2(vector: TestVector) bool { - if (__eqdf2(vector.a, vector.b) != vector.eqReference) { - return false; - } - if (__gedf2(vector.a, vector.b) != vector.geReference) { - return false; - } - if (__gtdf2(vector.a, vector.b) != vector.gtReference) { - return false; - } - if (__ledf2(vector.a, vector.b) != vector.leReference) { - return false; - } - if (__ltdf2(vector.a, vector.b) != vector.ltReference) { - return false; - } - if (__nedf2(vector.a, vector.b) != vector.neReference) { - return false; - } - if (__unorddf2(vector.a, vector.b) != vector.unReference) { - return false; - } - return true; -} +const impl = @import("comparef.zig"); +const Order = impl.Order; +const cmp_f64 = impl.cmp_f64; +const unord_f64 = impl.unord_f64; const arguments = [_]f64{ std.math.nan(f64), @@ -73,36 +33,20 @@ const arguments = [_]f64{ std.math.inf(f64), }; -fn generateVector(comptime a: f64, comptime b: f64) TestVector { - const leResult = if (a < b) -1 else if (a == b) 0 else 1; - const geResult = if (a > b) 1 else if (a == b) 0 else -1; - const unResult = if (a != a or b != b) 1 else 0; - return TestVector{ - .a = a, - .b = b, - .eqReference = leResult, - .geReference = geResult, - .gtReference = geResult, - .leReference = leResult, - .ltReference = leResult, - .neReference = leResult, - .unReference = unResult, - }; -} - -const test_vectors = init: { - @setEvalBranchQuota(10000); - var vectors: [arguments.len * arguments.len]TestVector = undefined; +test "compare f64" { for (arguments[0..], 0..) |arg_i, i| { for (arguments[0..], 0..) |arg_j, j| { - vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j); + const expected_unord = i == 0 or j == 0; + const expected_order: ?Order = if (expected_unord) null else switch (std.math.order( + if (i >= 9) i - 1 else i, + if (j >= 9) j - 1 else j, + )) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; + try std.testing.expect(expected_order == cmp_f64(arg_i, arg_j)); + try std.testing.expect(expected_unord == unord_f64(arg_i, arg_j)); } } - break :init vectors; -}; - -test "compare f64" { - for (test_vectors) |vector| { - try std.testing.expect(test__cmpdf2(vector)); - } } diff --git a/lib/compiler_rt/comparef.zig b/lib/compiler_rt/comparef.zig index a0f7551c74c9068909ef9e10c0ea71fa93140eef..7b397ba02f9aca5a534f015726bcb143a456eb63 100644 --- a/lib/compiler_rt/comparef.zig +++ b/lib/compiler_rt/comparef.zig @@ -1,163 +1,309 @@ +const builtin = @import("builtin"); const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; +const Unordered = if (builtin.cpu.arch == .avr) + i8 +else if (builtin.cpu.arch.isAARCH64()) + i32 +else if (builtin.target.cTypeBitSize(.long) >= builtin.target.ptrBitWidth()) + c_long +else + c_longlong; +pub const Order = enum(Unordered) { lt = -1, eq = 0, gt = 1 }; +const SparcOrder = enum(i32) { eq = 0, lt = 1, gt = 2, un = 3 }; + comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fcmpun, "__aeabi_fcmpun"); - } else { - symbol(&__unordsf2, "__unordsf2"); - } - - symbol(&__unordxf2, "__unordxf2"); - - symbol(&__eqhf2, "__eqhf2"); - symbol(&__nehf2, "__nehf2"); - symbol(&__lehf2, "__lehf2"); symbol(&__cmphf2, "__cmphf2"); - symbol(&__lthf2, "__lthf2"); + symbol(&__cmphf2, "__eqhf2"); + symbol(&__cmphf2, "__nehf2"); + symbol(&__cmphf2, "__lthf2"); + symbol(&__cmphf2, "__lehf2"); + symbol(&__gehf2, "__gthf2"); + symbol(&__gehf2, "__gehf2"); + symbol(&__unordhf2, "__unordhf2"); if (compiler_rt.want_aeabi) { symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq"); symbol(&__aeabi_fcmplt, "__aeabi_fcmplt"); symbol(&__aeabi_fcmple, "__aeabi_fcmple"); + symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt"); + symbol(&__aeabi_fcmpge, "__aeabi_fcmpge"); + symbol(&__aeabi_fcmpun, "__aeabi_fcmpun"); + + symbol(&__aeabi_dcmpeq, "__aeabi_dcmpeq"); + symbol(&__aeabi_dcmplt, "__aeabi_dcmplt"); + symbol(&__aeabi_dcmple, "__aeabi_dcmple"); + symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt"); + symbol(&__aeabi_dcmpge, "__aeabi_dcmpge"); + symbol(&__aeabi_dcmpun, "__aeabi_dcmpun"); } else { - symbol(&__eqsf2, "__eqsf2"); - symbol(&__nesf2, "__nesf2"); - symbol(&__lesf2, "__lesf2"); symbol(&__cmpsf2, "__cmpsf2"); - symbol(&__ltsf2, "__ltsf2"); + symbol(&__cmpsf2, "__eqsf2"); + symbol(&__cmpsf2, "__nesf2"); + symbol(&__cmpsf2, "__ltsf2"); + symbol(&__cmpsf2, "__lesf2"); + symbol(&__gesf2, "__gtsf2"); + symbol(&__gesf2, "__gesf2"); + symbol(&__unordsf2, "__unordsf2"); + + symbol(&__cmpdf2, "__cmpdf2"); + symbol(&__cmpdf2, "__eqdf2"); + symbol(&__cmpdf2, "__nedf2"); + symbol(&__cmpdf2, "__ltdf2"); + symbol(&__cmpdf2, "__ledf2"); + symbol(&__gedf2, "__gtdf2"); + symbol(&__gedf2, "__gedf2"); + symbol(&__unorddf2, "__unorddf2"); } + symbol(&__cmpxf2, "__cmpxf2"); + symbol(&__cmpxf2, "__eqxf2"); + symbol(&__cmpxf2, "__nexf2"); + symbol(&__cmpxf2, "__ltxf2"); + symbol(&__cmpxf2, "__lexf2"); + symbol(&__gexf2, "__gtxf2"); + symbol(&__gexf2, "__gexf2"); + symbol(&__unordxf2, "__unordxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__cmptf2, "__eqkf2"); + symbol(&__cmptf2, "__nekf2"); + symbol(&__cmptf2, "__ltkf2"); + symbol(&__cmptf2, "__lekf2"); + symbol(&__getf2, "__gtkf2"); + symbol(&__getf2, "__gekf2"); symbol(&__unordtf2, "__unordkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_cmp, "_Qp_cmp"); + symbol(&_Qp_feq, "_Qp_feq"); + symbol(&_Qp_fne, "_Qp_fne"); + symbol(&_Qp_flt, "_Qp_flt"); + symbol(&_Qp_fle, "_Qp_fle"); + symbol(&_Qp_fgt, "_Qp_fgt"); + symbol(&_Qp_fge, "_Qp_fge"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&_Q_cmp, "_Q_cmp"); + symbol(&_Q_feq, "_Q_feq"); + symbol(&_Q_fne, "_Q_fne"); + symbol(&_Q_flt, "_Q_flt"); + symbol(&_Q_fle, "_Q_fle"); + symbol(&_Q_fgt, "_Q_fgt"); + symbol(&_Q_fge, "_Q_fge"); + } else { + symbol(&__cmptf2, "__cmptf2"); + symbol(&__cmptf2, "__eqtf2"); + symbol(&__cmptf2, "__netf2"); + symbol(&__cmptf2, "__lttf2"); + symbol(&__cmptf2, "__letf2"); + symbol(&__getf2, "__gttf2"); + symbol(&__getf2, "__getf2"); + symbol(&__unordtf2, "__unordtf2"); } - symbol(&__unordtf2, "__unordtf2"); - symbol(&__unordhf2, "__unordhf2"); } -pub fn __unordhf2(a: f16, b: f16) callconv(.c) i32 { - return unordcmp(f16, a, b); +fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { + return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt; } - -pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 { - return unordcmp(f128, a, b); +fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { + return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt; } - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`, -/// and `__ltsf2`. -fn __cmpsf2(a: f32, b: f32) callconv(.c) i32 { - return @backingInt(cmpf2(f32, LE, a, b)); +fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); } - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -pub fn __lesf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +pub fn cmp_f16(a: f16, b: f16) ?Order { + return cmpf2(f16, a, b); } - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined -/// to have the same return value. -pub fn __eqsf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +pub fn unord_f16(a: f16, b: f16) bool { + return unord(f16, a, b); } -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined -/// to have the same return value. -pub fn __nesf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); +fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { + return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt; } - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 { - return __cmpsf2(a, b); -} - fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) == .Equal); + return @intFromBool(cmp_f32(a, b) == .eq); } - fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) == .Less); + return @intFromBool(cmp_f32(a, b) == .lt); } - fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmpf2(f32, LE, a, b) != .Greater); + return @intFromBool(cmp_f32(a, b) orelse .gt != .gt); } - -/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; -/// if a is greater than b, they return 1; and if a and b are equal they return 0. -/// If either argument is NaN they return 1..." -/// -/// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`, -/// and `__lthf2`. -fn __cmphf2(a: f16, b: f16) callconv(.c) i32 { - return @backingInt(cmpf2(f16, LE, a, b)); +fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { + return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt; } - -/// "These functions return a value less than or equal to zero if neither argument is NaN, -/// and a is less than or equal to b." -fn __lehf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f32(a, b) orelse .lt != .lt); } - -/// "These functions return zero if neither argument is NaN, and a and b are equal." -/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined -/// to have the same return value. -fn __eqhf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f32(a, b) == .gt); } - -/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." -/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined -/// to have the same return value. -fn __nehf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); +fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); } - -/// "These functions return a value less than zero if neither argument is NaN, and a -/// is strictly less than b." -fn __lthf2(a: f16, b: f16) callconv(.c) i32 { - return __cmphf2(a, b); -} - -fn __unordxf2(a: f80, b: f80) callconv(.c) i32 { - return unordcmp(f80, a, b); -} - -pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 { - return unordcmp(f32, a, b); -} - fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return unordcmp(f32, a, b); + return @intFromBool(unord_f32(a, b)); } +pub fn cmp_f32(a: f32, b: f32) ?Order { + return cmpf2(f32, a, b); +} +pub fn unord_f32(a: f32, b: f32) bool { + return unord(f32, a, b); +} + +fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { + return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .gt; +} +fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .eq); +} +fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .lt); +} +fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) orelse .gt != .gt); +} +fn __gedf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { + return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .lt; +} +fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) orelse .lt != .lt); +} +fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(cmp_f64(a, b) == .gt); +} +fn __unorddf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return @intFromBool(unord_f64(a, b)); +} +pub fn cmp_f64(a: f64, b: f64) ?Order { + return cmpf2(f64, a, b); +} +pub fn unord_f64(a: f64, b: f64) bool { + return unord(f64, a, b); +} + +fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order { + return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .gt; +} +fn __gexf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order { + return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .lt; +} +fn __unordxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn cmp_f80(a: f80, b: f80) ?Order { + const a_rep = std.math.F80.fromFloat(a); + const b_rep = std.math.F80.fromFloat(b); + const sig_bits = std.math.floatMantissaBits(f80); + const int_bit = 0x8000000000000000; + const sign_bit = 0x8000; + const special_exp = 0x7FFF; -pub const LE = enum(i32) { - Less = -1, - Equal = 0, - Greater = 1, + // If either a or b is NaN, they are unordered. + if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or + (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) + return null; - const Unordered: LE = .Greater; -}; + // If a and b are both zeros, they are equal. + if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) + return .eq; -pub const GE = enum(i32) { - Less = -1, - Equal = 0, - Greater = 1, + if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { + return .eq; + } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { + // signs are different + if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { + return .lt; + } else { + return .gt; + } + } else { + const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); + const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); + if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { + return .lt; + } else { + return .gt; + } + } +} +pub fn unord_f80(a: f80, b: f80) bool { + return unord(f80, a, b); +} - const Unordered: GE = .Less; -}; +fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order { + return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .gt; +} +fn __getf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order { + return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .lt; +} +fn __unordtf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Unordered { + return @intFromBool(unord_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) SparcOrder { + return switch (cmp_f128(a.*, b.*) orelse return .un) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; +} +fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .eq); +} +fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) != .eq); +} +fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .lt); +} +fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a.*, b.*) orelse .gt) != .gt); +} +fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a.*, b.*) == .gt); +} +fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a.*, b.*) orelse .lt) != .lt); +} +fn _Q_cmp(a: f128, b: f128) callconv(.c) SparcOrder { + return switch (cmp_f128(a, b) orelse return .un) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; +} +fn _Q_feq(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .eq); +} +fn _Q_fne(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) != .eq); +} +fn _Q_flt(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .lt); +} +fn _Q_fle(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a, b) orelse .gt) != .gt); +} +fn _Q_fgt(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool(cmp_f128(a, b) == .gt); +} +fn _Q_fge(a: f128, b: f128) callconv(.c) i32 { + return @intFromBool((cmp_f128(a, b) orelse .lt) != .lt); +} +pub fn cmp_f128(a: f128, b: f128) ?Order { + return cmpf2(f128, a, b); +} +pub fn unord_f128(a: f128, b: f128) bool { + return unord(f128, a, b); +} -pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { +inline fn cmpf2(comptime T: type, a: T, b: T) ?Order { const bits = @typeInfo(T).float.bits; const srep_t = @Int(.signed, bits); const rep_t = @Int(.unsigned, bits); @@ -175,81 +321,42 @@ pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { const bAbs = @as(rep_t, @bitCast(bInt)) & absMask; // If either a or b is NaN, they are unordered. - if (aAbs > infRep or bAbs > infRep) return RT.Unordered; + if (aAbs > infRep or bAbs > infRep) return null; // If a and b are both zeros, they are equal. - if ((aAbs | bAbs) == 0) return .Equal; + if ((aAbs | bAbs) == 0) return .eq; // If at least one of a and b is positive, we get the same result comparing // a and b as signed integers as we would with a floating-point compare. if ((aInt & bInt) >= 0) { if (aInt < bInt) { - return .Less; + return .lt; } else if (aInt == bInt) { - return .Equal; - } else return .Greater; + return .eq; + } else return .gt; } else { // Otherwise, both are negative, so we need to flip the sense of the // comparison to get the correct result. (This assumes a twos- or ones- // complement integer representation; if integers are represented in a // sign-magnitude representation, then this flip is incorrect). if (aInt > bInt) { - return .Less; + return .lt; } else if (aInt == bInt) { - return .Equal; - } else return .Greater; + return .eq; + } else return .gt; } } -pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { - const a_rep = std.math.F80.fromFloat(a); - const b_rep = std.math.F80.fromFloat(b); - const sig_bits = std.math.floatMantissaBits(f80); - const int_bit = 0x8000000000000000; - const sign_bit = 0x8000; - const special_exp = 0x7FFF; - - // If either a or b is NaN, they are unordered. - if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or - (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) - return RT.Unordered; - - // If a and b are both zeros, they are equal. - if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) - return .Equal; - - if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { - return .Equal; - } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { - // signs are different - if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { - return .Less; - } else { - return .Greater; - } - } else { - const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); - const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); - if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { - return .Less; - } else { - return .Greater; - } - } -} - -test "cmp_f80" { - inline for (.{ LE, GE }) |RT| { - try std.testing.expect(cmp_f80(RT, 1.0, 1.0) == RT.Equal); - try std.testing.expect(cmp_f80(RT, 0.0, -0.0) == RT.Equal); - try std.testing.expect(cmp_f80(RT, 2.0, 4.0) == RT.Less); - try std.testing.expect(cmp_f80(RT, 2.0, -4.0) == RT.Greater); - try std.testing.expect(cmp_f80(RT, -2.0, -4.0) == RT.Greater); - try std.testing.expect(cmp_f80(RT, -2.0, 4.0) == RT.Less); - } +test cmp_f80 { + try std.testing.expect(cmp_f80(1.0, 1.0) == .eq); + try std.testing.expect(cmp_f80(0.0, -0.0) == .eq); + try std.testing.expect(cmp_f80(2.0, 4.0) == .lt); + try std.testing.expect(cmp_f80(2.0, -4.0) == .gt); + try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt); + try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt); } -pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { +inline fn unord(comptime T: type, a: T, b: T) bool { const rep_t = @Int(.unsigned, @typeInfo(T).float.bits); const significandBits = std.math.floatMantissaBits(T); @@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask; const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask; - return @intFromBool(aAbs > infRep or bAbs > infRep); + return aAbs > infRep or bAbs > infRep; } test { diff --git a/lib/compiler_rt/comparesf2_test.zig b/lib/compiler_rt/comparesf2_test.zig index d42e1ca6db124de615f2eb3a74eadfeb119992eb..5e34b00604b8f7d608cb6d21e51d8118d26d013b 100644 --- a/lib/compiler_rt/comparesf2_test.zig +++ b/lib/compiler_rt/comparesf2_test.zig @@ -5,52 +5,12 @@ const std = @import("std"); const builtin = @import("builtin"); -const __eqsf2 = @import("./comparef.zig").__eqsf2; -const __lesf2 = @import("./comparef.zig").__lesf2; -const __ltsf2 = @import("./comparef.zig").__ltsf2; -const __nesf2 = @import("./comparef.zig").__nesf2; +const compiler_rt = @import("../compiler_rt.zig"); -const __gesf2 = @import("./gesf2.zig").__gesf2; -const __gtsf2 = @import("./gesf2.zig").__gtsf2; - -const __unordsf2 = @import("./comparef.zig").__unordsf2; - -const TestVector = struct { - a: f32, - b: f32, - eqReference: c_int, - geReference: c_int, - gtReference: c_int, - leReference: c_int, - ltReference: c_int, - neReference: c_int, - unReference: c_int, -}; - -fn test__cmpsf2(vector: TestVector) bool { - if (__eqsf2(vector.a, vector.b) != vector.eqReference) { - return false; - } - if (__gesf2(vector.a, vector.b) != vector.geReference) { - return false; - } - if (__gtsf2(vector.a, vector.b) != vector.gtReference) { - return false; - } - if (__lesf2(vector.a, vector.b) != vector.leReference) { - return false; - } - if (__ltsf2(vector.a, vector.b) != vector.ltReference) { - return false; - } - if (__nesf2(vector.a, vector.b) != vector.neReference) { - return false; - } - if (__unordsf2(vector.a, vector.b) != vector.unReference) { - return false; - } - return true; -} +const impl = @import("comparef.zig"); +const Order = impl.Order; +const cmp_f32 = impl.cmp_f32; +const unord_f32 = impl.unord_f32; const arguments = [_]f32{ std.math.nan(f32), @@ -73,36 +33,20 @@ const arguments = [_]f32{ std.math.inf(f32), }; -fn generateVector(comptime a: f32, comptime b: f32) TestVector { - const leResult = if (a < b) -1 else if (a == b) 0 else 1; - const geResult = if (a > b) 1 else if (a == b) 0 else -1; - const unResult = if (a != a or b != b) 1 else 0; - return TestVector{ - .a = a, - .b = b, - .eqReference = leResult, - .geReference = geResult, - .gtReference = geResult, - .leReference = leResult, - .ltReference = leResult, - .neReference = leResult, - .unReference = unResult, - }; -} - -const test_vectors = init: { - @setEvalBranchQuota(10000); - var vectors: [arguments.len * arguments.len]TestVector = undefined; +test "compare f32" { for (arguments[0..], 0..) |arg_i, i| { for (arguments[0..], 0..) |arg_j, j| { - vectors[(i * arguments.len) + j] = generateVector(arg_i, arg_j); + const expected_unord = i == 0 or j == 0; + const expected_order: ?Order = if (expected_unord) null else switch (std.math.order( + i - @intFromBool(i >= 9), + j - @intFromBool(j >= 9), + )) { + .lt => .lt, + .eq => .eq, + .gt => .gt, + }; + try std.testing.expect(expected_order == cmp_f32(arg_i, arg_j)); + try std.testing.expect(expected_unord == unord_f32(arg_i, arg_j)); } } - break :init vectors; -}; - -test "compare f32" { - for (test_vectors) |vector| { - try std.testing.expect(test__cmpsf2(vector)); - } } diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index a207f0244f941c3e6730f9e6f5891201840120cc..612698b1e9efb080804656c50e68cd6e0a2e8680 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -13,31 +13,35 @@ const expect = std.testing.expect; const expectApproxEqAbs = std.testing.expectApproxEqAbs; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; comptime { - symbol(&cosh, "__cosh"); - symbol(&cosl, "__cosl"); + symbol(&__cosh, "__cosh"); symbol(&cosf, "cosf"); symbol(&cos, "cos"); - symbol(&cosx, "__cosx"); - if (compiler_rt.want_ppc_abi) { - symbol(&cosq, "cosf128"); - } + symbol(&__cosx, "__cosx"); + if (compiler_rt.want_ppc_abi) symbol(&cosq, "cosf128"); symbol(&cosq, "cosq"); symbol(&cosl, "cosl"); + symbol(&cosl, "__cosl"); // required by musl } -pub fn cosh(a: f16) callconv(.c) f16 { +fn __cosh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(cos_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn cos_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(cosf(a)); + return @floatCast(cos_f32(x)); } -pub fn cosf(x: f32) callconv(.c) f32 { +fn cosf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(cos_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn cos_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -94,7 +98,10 @@ pub fn cosf(x: f32) callconv(.c) f32 { }; } -pub fn cos(x: f64) callconv(.c) f64 { +fn cos(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(cos_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn cos_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -123,7 +130,10 @@ pub fn cos(x: f64) callconv(.c) f64 { }; } -pub fn cosx(x: f80) callconv(.c) f80 { +fn __cosx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(cos_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn cos_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -147,7 +157,10 @@ pub fn cosx(x: f80) callconv(.c) f80 { }; } -pub fn cosq(x: f128) callconv(.c) f128 { +fn cosq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(cos_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn cos_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -173,20 +186,21 @@ pub fn cosq(x: f128) callconv(.c) f128 { pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return cos(x), - 80 => return cosx(x), - 128 => return cosq(x), - else => @compileError("unreachable"), + 64 => return cos_f64(x), + 80 => return cos_f80(x), + 128 => return cos_f128(x), + else => comptime unreachable, } } fn testCosSpecial(comptime T: type) !void { const f = switch (T) { - f32 => cosf, - f64 => cos, - f80 => cosx, - f128 => cosq, - else => @compileError("unimplemented"), + f16 => cos_f16, + f32 => cos_f32, + f64 => cos_f64, + f80 => cos_f80, + f128 => cos_f128, + else => comptime unreachable, }; try expect(f(0.0) == 1.0); @@ -198,13 +212,13 @@ fn testCosSpecial(comptime T: type) !void { test "cos32.normal" { const epsilon = math.floatEps(f32); - try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon); - try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon); - try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon); - try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon); - try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon); - try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon); - try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon); + try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon); + try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon); + try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon); + try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon); + try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon); + try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon); + try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon); } test "cos32.special" { @@ -213,13 +227,13 @@ test "cos32.special" { test "cos64.normal" { const epsilon = math.floatEps(f64); - try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon); - try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon); - try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon); - try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon); - try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon); - try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon); - try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon); + try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon); + try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon); + try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon); + try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon); + try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon); + try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon); + try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon); } test "cos64.special" { @@ -228,13 +242,13 @@ test "cos64.special" { test "cos80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon); - try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon); + try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon); } test "cos80.special" { @@ -243,13 +257,13 @@ test "cos80.special" { test "cos128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon); - try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon); + try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon); } test "cos128.special" { diff --git a/lib/compiler_rt/count0bits.zig b/lib/compiler_rt/count0bits.zig index a8d0445dc69276e4639211818eb42707a8782c6c..fca372b33b98865ec041ee3ca764a5d8207ae330 100644 --- a/lib/compiler_rt/count0bits.zig +++ b/lib/compiler_rt/count0bits.zig @@ -1,6 +1,7 @@ const builtin = @import("builtin"); const std = @import("std"); -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__clzsi2, "__clzsi2"); diff --git a/lib/compiler_rt/divc3.zig b/lib/compiler_rt/divc3.zig index 92d2b39f663d272bdb83042f69abcd6a91c2ba09..a76a63c7e0f9059a112dc5c3b4406349766351f6 100644 --- a/lib/compiler_rt/divc3.zig +++ b/lib/compiler_rt/divc3.zig @@ -7,12 +7,81 @@ const maxInt = std.math.maxInt; const minInt = std.math.minInt; const isFinite = std.math.isFinite; const copysign = std.math.copysign; -const Complex = @import("mulc3.zig").Complex; + +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const Complex = compiler_rt.Complex; + +comptime { + if (@import("builtin").zig_backend != .stage2_c) { + symbol(&__divhc3, "__divhc3"); + symbol(&__divsc3, "__divsc3"); + symbol(&__divdc3, "__divdc3"); + symbol(&__divxc3, "__divxc3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__divtc3, "__divkc3"); + } else { + symbol(&__divtc3, "__divtc3"); + } + } +} + +fn __divhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { + return compiler_rt.f16.complex.toAbi(div_cf16( + compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { + return divc3(f16, a, b); +} + +fn __divsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { + return compiler_rt.f32.complex.toAbi(div_cf32( + compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { + return divc3(f32, a, b); +} + +fn __divdc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { + return compiler_rt.f64.complex.toAbi(div_cf64( + compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { + return divc3(f64, a, b); +} + +fn __divxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { + return compiler_rt.f80.complex.toAbi(div_cf80( + compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { + return divc3(f80, a, b); +} + +fn __divtc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { + return compiler_rt.f128.complex.toAbi(div_cf128( + compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn div_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { + return divc3(f128, a, b); +} /// Implementation based on Annex G of C17 Standard (N2176) -pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { - var c = c_in; - var d = d_in; +inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { + const a = lhs.real; + const b = lhs.imag; + var c = rhs.real; + var d = rhs.imag; // logbw used to prevent under/over-flow const logbw = ilogb(@max(@abs(c), @abs(d))); @@ -23,7 +92,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { break :b logbw; } else 0; const denom = c * c + d * d; - const result = Complex(T){ + const result: Complex(T) = .{ .real = scalbn((a * c + b * d) / denom, -ilogbw), .imag = scalbn((b * c - a * d) / denom, -ilogbw), }; @@ -58,3 +127,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { return result; } + +test { + _ = @import("divc3_test.zig"); +} diff --git a/lib/compiler_rt/divc3_test.zig b/lib/compiler_rt/divc3_test.zig index d3c400d46cacb1f12ec677d0f5dd0fb661bace4d..277a879253eed991a5e2cfa8453e8d28ab589f21 100644 --- a/lib/compiler_rt/divc3_test.zig +++ b/lib/compiler_rt/divc3_test.zig @@ -2,76 +2,53 @@ const std = @import("std"); const math = std.math; const expect = std.testing.expect; -const Complex = @import("./mulc3.zig").Complex; -const __divhc3 = @import("./divhc3.zig").__divhc3; -const __divsc3 = @import("./divsc3.zig").__divsc3; -const __divdc3 = @import("./divdc3.zig").__divdc3; -const __divxc3 = @import("./divxc3.zig").__divxc3; -const __divtc3 = @import("./divtc3.zig").__divtc3; +const Complex = @import("../compiler_rt.zig").Complex; + +const impl = @import("divc3.zig"); +const div_cf16 = impl.div_cf16; +const div_cf32 = impl.div_cf32; +const div_cf64 = impl.div_cf64; +const div_cf80 = impl.div_cf80; +const div_cf128 = impl.div_cf128; test "divc3" { - try testDiv(f16, __divhc3); - try testDiv(f32, __divsc3); - try testDiv(f64, __divdc3); - try testDiv(f80, __divxc3); - try testDiv(f128, __divtc3); + try testDiv(f16, div_cf16); + try testDiv(f32, div_cf32); + try testDiv(f64, div_cf64); + try testDiv(f80, div_cf80); + try testDiv(f128, div_cf128); } -fn testDiv(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { +fn testDiv(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); try expect(result.real == -1.0); - try expect(result.imag == 0.0); + try expect(math.isNegativeZero(result.imag)); } { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -4.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); try expect(result.real == -0.25); - try expect(result.imag == 0.0); + try expect(math.isNegativeZero(result.imag)); } { // if the first operand is an infinity and the second operand is a finite number, then the - // result of the / operator is an infinity; - const a: T = -math.inf(T); - const b: T = 0.0; - const c: T = -4.0; - const d: T = 1.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + // resultult of the / operator is an infinity; + const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } { // if the first operand is a finite number and the second operand is an infinity, then the // result of the / operator is a zero; - const a: T = 17.2; - const b: T = 0.0; - const c: T = -math.inf(T); - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == -0.0); - try expect(result.imag == 0.0); + const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 }); + try expect(math.isNegativeZero(result.real)); + try expect(math.isNegativeZero(result.imag)); } { // if the first operand is a nonzero finite number or an infinity and the second operand is // a zero, then the result of the / operator is an infinity - const a: T = 1.1; - const b: T = 0.1; - const c: T = 0.0; - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } } diff --git a/lib/compiler_rt/divdc3.zig b/lib/compiler_rt/divdc3.zig deleted file mode 100644 index e26dd26d61552832bcd1d19c022e8b0455551a40..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divdc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divdc3, "__divdc3"); - } -} - -pub fn __divdc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) Complex(f64) { - return divc3.divc3(f64, a, b, c, d); -} diff --git a/lib/compiler_rt/divdf3.zig b/lib/compiler_rt/divdf3.zig index 3ad767dbf2292d403aa0e2aafbdaf20f80ff9571..90953e0d0616d6a211872eef0b0c18ba1ff0cdb4 100644 --- a/lib/compiler_rt/divdf3.zig +++ b/lib/compiler_rt/divdf3.zig @@ -17,15 +17,15 @@ comptime { } } -pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 { - return div(a, b); +fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); } fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return div(a, b); + return div_f64(a, b); } -inline fn div(a: f64, b: f64) f64 { +pub fn div_f64(a: f64, b: f64) f64 { const Z = @Int(.unsigned, 64); const SignedZ = @Int(.signed, 64); diff --git a/lib/compiler_rt/divdf3_test.zig b/lib/compiler_rt/divdf3_test.zig index 45de9b27ef794706fc6e0e297f4289be3ae549fc..cd927bafc4d28921e9fb0bf191537b43cb953986 100644 --- a/lib/compiler_rt/divdf3_test.zig +++ b/lib/compiler_rt/divdf3_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divdf3 = @import("divdf3.zig").__divdf3; +const div_f64 = @import("divdf3.zig").div_f64; const nanRep: u64 = @as(u64, @bitCast(math.nan(f64))); const infRep: u64 = @as(u64, @bitCast(math.inf(f64))); @@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool { } fn test__divdf3(a: f64, b: f64, expected: u64) !void { - const x = __divdf3(a, b); + const x = div_f64(a, b); const ret = compareResultD(x, expected); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divhc3.zig b/lib/compiler_rt/divhc3.zig deleted file mode 100644 index c9668f4ca8ae84840ab3ee65446b682b6223832b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divhc3.zig +++ /dev/null @@ -1,14 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divhc3, "__divhc3"); - } -} - -pub fn __divhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) Complex(f16) { - return divc3.divc3(f16, a, b, c, d); -} diff --git a/lib/compiler_rt/divhf3.zig b/lib/compiler_rt/divhf3.zig deleted file mode 100644 index fc2710ff2761fce7e8822583b86aefc562f98486..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divsf3 = @import("./divsf3.zig"); - -comptime { - symbol(&__divhf3, "__divhf3"); -} - -pub fn __divhf3(a: f16, b: f16) callconv(.c) f16 { - // TODO: more efficient implementation - return @floatCast(divsf3.__divsf3(a, b)); -} diff --git a/lib/compiler_rt/divmodei4.zig b/lib/compiler_rt/divmodei4.zig index 55c7ec5792549933d22e8962f58b8cb6e23a5d54..9198951fe554a89cd2f65c69ce3fea087952db0a 100644 --- a/lib/compiler_rt/divmodei4.zig +++ b/lib/compiler_rt/divmodei4.zig @@ -5,7 +5,7 @@ const std = @import("std"); const compiler_rt = @import("../compiler_rt.zig"); const udivmod = @import("udivmodei4.zig").divmod; -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__divei4, "__divei4"); diff --git a/lib/compiler_rt/divsc3.zig b/lib/compiler_rt/divsc3.zig deleted file mode 100644 index 9378bfab8ce80584b3b5b1b6d1fbd70200ef6648..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divsc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divsc3, "__divsc3"); - } -} - -pub fn __divsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) Complex(f32) { - return divc3.divc3(f32, a, b, c, d); -} diff --git a/lib/compiler_rt/divsf3.zig b/lib/compiler_rt/divsf3.zig index c0fbcb92b743fff4e12db533d7694210e7ebb0a2..c86c860948d315b260498c959e4678f5f64b9e94 100644 --- a/lib/compiler_rt/divsf3.zig +++ b/lib/compiler_rt/divsf3.zig @@ -9,6 +9,7 @@ const symbol = compiler_rt.symbol; const normalize = compiler_rt.normalize; comptime { + symbol(&__divhf3, "__divhf3"); if (compiler_rt.want_aeabi) { symbol(&__aeabi_fdiv, "__aeabi_fdiv"); } else { @@ -16,15 +17,23 @@ comptime { } } -pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 { - return div(a, b); +fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(div_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn div_f16(a: f16, b: f16) f16 { + // TODO: more efficient implementation + return @floatCast(div_f32(a, b)); +} + +fn __divsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(div_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); } fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return div(a, b); + return div_f32(a, b); } -inline fn div(a: f32, b: f32) f32 { +pub fn div_f32(a: f32, b: f32) f32 { const Z = @Int(.unsigned, 32); const significandBits = std.math.floatMantissaBits(f32); diff --git a/lib/compiler_rt/divsf3_test.zig b/lib/compiler_rt/divsf3_test.zig index c457915e49cd41986f1470b2f868398cfad855e9..f12e152b31b41b1fd85d1f1493838dd68a43f983 100644 --- a/lib/compiler_rt/divsf3_test.zig +++ b/lib/compiler_rt/divsf3_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divsf3 = @import("divsf3.zig").__divsf3; +const div_f32 = @import("divsf3.zig").div_f32; const nanRep: u32 = @as(u32, @bitCast(math.nan(f32))); const infRep: u32 = @as(u32, @bitCast(math.inf(f32))); @@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool { } fn test__divsf3(a: f32, b: f32, expected: u32) !void { - const x = __divsf3(a, b); + const x = div_f32(a, b); const ret = compareResultF(x, expected); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divtc3.zig b/lib/compiler_rt/divtc3.zig deleted file mode 100644 index b0e0f35f5447488f4d15ba76ede68bab2425f96b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divtc3.zig +++ /dev/null @@ -1,16 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - if (compiler_rt.want_ppc_abi) - symbol(&__divtc3, "__divkc3"); - symbol(&__divtc3, "__divtc3"); - } -} - -pub fn __divtc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) Complex(f128) { - return divc3.divc3(f128, a, b, c, d); -} diff --git a/lib/compiler_rt/divtf3.zig b/lib/compiler_rt/divtf3.zig index 3b6f648e3ac33e2fb3183bdd7fcb892ea239500c..9995a9bfd796070d9573ac050bf233c9646a5d98 100644 --- a/lib/compiler_rt/divtf3.zig +++ b/lib/compiler_rt/divtf3.zig @@ -13,19 +13,20 @@ comptime { symbol(&_Qp_div, "_Qp_div"); } else if (compiler_rt.want_sparc32_abi) { symbol(&__divtf3, "_Q_div"); + } else { + symbol(&__divtf3, "__divtf3"); } - symbol(&__divtf3, "__divtf3"); } -pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 { - return div(a, b); +fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); } fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = div(a.*, b.*); + c.* = div_f128(a.*, b.*); } -inline fn div(a: f128, b: f128) f128 { +pub fn div_f128(a: f128, b: f128) f128 { const Z = @Int(.unsigned, 128); const significandBits = std.math.floatMantissaBits(f128); diff --git a/lib/compiler_rt/divtf3_test.zig b/lib/compiler_rt/divtf3_test.zig index 4d10e5c39d7dc61b1c317364750757148635543d..dfc7e1e954ea96eb6927f4c56179efc15fe4a2ee 100644 --- a/lib/compiler_rt/divtf3_test.zig +++ b/lib/compiler_rt/divtf3_test.zig @@ -2,7 +2,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divtf3 = @import("divtf3.zig").__divtf3; +const div_f128 = @import("divtf3.zig").div_f128; fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { const rep: u128 = @bitCast(result); @@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { } fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void { - const x = __divtf3(a, b); + const x = div_f128(a, b); const ret = compareResultLD(x, expectedHi, expectedLo); try testing.expect(ret == true); } diff --git a/lib/compiler_rt/divxc3.zig b/lib/compiler_rt/divxc3.zig deleted file mode 100644 index 86c737a83931c6c34f73303eeaba00536d8e1bd4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/divxc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const divc3 = @import("./divc3.zig"); -const Complex = @import("./mulc3.zig").Complex; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__divxc3, "__divxc3"); - } -} - -pub fn __divxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) Complex(f80) { - return divc3.divc3(f80, a, b, c, d); -} diff --git a/lib/compiler_rt/divxf3.zig b/lib/compiler_rt/divxf3.zig index fdf43dc83bce6adbb53995826c516aecd7310fe2..eb3fde6862ab3937e8828d729287a35ea9d3ead9 100644 --- a/lib/compiler_rt/divxf3.zig +++ b/lib/compiler_rt/divxf3.zig @@ -11,7 +11,10 @@ comptime { symbol(&__divxf3, "__divxf3"); } -pub fn __divxf3(a: f80, b: f80) callconv(.c) f80 { +fn __divxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(div_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn div_f80(a: f80, b: f80) f80 { const T = f80; const Z = @Int(.unsigned, @bitSizeOf(T)); diff --git a/lib/compiler_rt/divxf3_test.zig b/lib/compiler_rt/divxf3_test.zig index cb897a1014022d50e8cb93043749b033b56af55d..88d7cada4606920997b5b0030134aaab476da576 100644 --- a/lib/compiler_rt/divxf3_test.zig +++ b/lib/compiler_rt/divxf3_test.zig @@ -2,7 +2,7 @@ const std = @import("std"); const math = std.math; const testing = std.testing; -const __divxf3 = @import("divxf3.zig").__divxf3; +const div_f80 = @import("divxf3.zig").div_f80; const nanRep: u80 = @as(u80, @bitCast(math.nan(f80))); const infRep: u80 = @as(u80, @bitCast(math.inf(f80))); @@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool { } fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void { - const x = __divxf3(a, b); + const x = div_f80(a, b); const ret = compareResult(x, expected); try testing.expect(ret == true); } fn test__divxf3(a: f80, b: f80) !void { const integerBit = 1 << math.floatFractionalBits(f80); - const x = __divxf3(a, b); + const x = div_f80(a, b); // Next float (assuming normal, non-zero result) const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit); diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index ce2eadb7f1edfe49ca51562a8b3ec4432f2017eb..ddec21869f166538e3497bb84050e55eba3ff33c 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -14,7 +14,7 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__exph, "__exph"); @@ -28,12 +28,18 @@ comptime { symbol(&expl, "expl"); } -pub fn __exph(a: f16) callconv(.c) f16 { +fn __exph(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(exp_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn exp_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(expf(a)); + return @floatCast(exp_f32(x)); } -pub fn expf(x_: f32) callconv(.c) f32 { +fn expf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(exp_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn exp_f32(x_: f32) f32 { const half = [_]f32{ 0.5, -0.5 }; const ln2hi = 6.9314575195e-1; const ln2lo = 1.4286067653e-6; @@ -108,7 +114,10 @@ pub fn expf(x_: f32) callconv(.c) f32 { } } -pub fn exp(x_: f64) callconv(.c) f64 { +fn exp(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(exp_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn exp_f64(x_: f64) f64 { const half = [_]f64{ 0.5, -0.5 }; const ln2hi: f64 = 6.93147180369123816490e-01; const ln2lo: f64 = 1.90821492927058770002e-10; @@ -189,116 +198,121 @@ pub fn exp(x_: f64) callconv(.c) f64 { } } -pub fn __expx(a: f80) callconv(.c) f80 { +fn __expx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(exp_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn exp_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(expq(a)); + return @floatCast(exp_f128(x)); } -const expq = @import("exp_f128.zig").exp; +fn expq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(exp_f128(compiler_rt.f128.fromAbi(x))); +} +pub const exp_f128 = @import("exp_f128.zig").exp; pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return exp(x), - 80 => return __expx(x), - 128 => return expq(x), - else => @compileError("unreachable"), + 64 => return exp_f64(x), + 80 => return exp_f80(x), + 128 => return exp_f128(x), + else => comptime unreachable, } } test "expf() special" { - try expectEqual(expf(0.0), 1.0); - try expectEqual(expf(-0.0), 1.0); - try expectEqual(expf(1.0), math.e); - try expectEqual(expf(math.ln2), 2.0); - try expectEqual(expf(math.inf(f32)), math.inf(f32)); - try expect(math.isPositiveZero(expf(-math.inf(f32)))); - try expect(math.isNan(expf(math.nan(f32)))); - try expect(math.isNan(expf(math.snan(f32)))); + try expectEqual(exp_f32(0.0), 1.0); + try expectEqual(exp_f32(-0.0), 1.0); + try expectEqual(exp_f32(1.0), math.e); + try expectEqual(exp_f32(math.ln2), 2.0); + try expectEqual(exp_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isPositiveZero(exp_f32(-math.inf(f32)))); + try expect(math.isNan(exp_f32(math.nan(f32)))); + try expect(math.isNan(exp_f32(math.snan(f32)))); } test "expf() sanity" { - try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12); - try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6); - try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13); - try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10); - try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13); - try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0); - try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1); - try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0); - try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1); - try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1); - try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8); - try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20); - try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25); - try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20); - try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8); - try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2); - try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16); - try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24); - try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5); - try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28); + try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12); + try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6); + try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13); + try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10); + try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13); + try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0); + try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1); + try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0); + try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1); + try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1); + try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8); + try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20); + try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25); + try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20); + try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8); + try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2); + try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16); + try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24); + try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5); + try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28); } test "expf() boundary" { - try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite - try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf - try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value - try expectEqual(expf(0x1p-149), 1.0); // Min positive input value - try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value - try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input - try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input - try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero - try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero - try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal - try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal - + try expectEqual(exp_f32(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite + try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf + try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value + try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value + try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value + try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input + try expectEqual(exp_f32(-0x1p-126), 1.0); // First negative subnormal input + try expectEqual(exp_f32(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero + try expectEqual(exp_f32(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero + try expectEqual(exp_f32(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal + try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal } test "exp() special" { - try expectEqual(exp(0.0), 1.0); - try expectEqual(exp(-0.0), 1.0); + try expectEqual(exp_f64(0.0), 1.0); + try expectEqual(exp_f64(-0.0), 1.0); // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC // try expectEqual(exp(1.0), math.e); - try expectEqual(exp(math.ln2), 2.0); - try expectEqual(exp(math.inf(f64)), math.inf(f64)); - try expect(math.isPositiveZero(exp(-math.inf(f64)))); - try expect(math.isNan(exp(math.nan(f64)))); - try expect(math.isNan(exp(math.snan(f64)))); + try expectEqual(exp_f64(math.ln2), 2.0); + try expectEqual(exp_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isPositiveZero(exp_f64(-math.inf(f64)))); + try expect(math.isNan(exp_f64(math.nan(f64)))); + try expect(math.isNan(exp_f64(math.snan(f64)))); } test "exp() sanity" { - try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); - try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); - try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); - try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); - try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); - try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); - try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); - try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); - try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); - try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); - try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); - try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); - try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); - try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); - try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); - try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); - try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); - try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); - try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); - try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); + try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); + try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); + try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); + try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); + try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); + try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); + try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); + try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); + try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); + try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); + try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); + try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); + try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); + try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); + try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); + try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); + try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); + try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); + try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); + try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); } test "exp() boundary" { - try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite - try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf - try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value - try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value - try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value - try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input - try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input - try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero - try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero - try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal - try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal + try expectEqual(exp_f64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite + try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf + try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value + try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value + try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value + try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input + try expectEqual(exp_f64(-0x1p-1022), 1.0); // First negative subnormal input + try expectEqual(exp_f64(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero + try expectEqual(exp_f64(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero + try expectEqual(exp_f64(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal + try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal } diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index abcef881073619a860997766283c950cc702a3e6..36ee7c14c90be2c13dd0e09ca91d656a19a539a7 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -26,12 +26,18 @@ comptime { symbol(&exp2l, "exp2l"); } -pub fn __exp2h(x: f16) callconv(.c) f16 { +fn __exp2h(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(exp2_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn exp2_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(exp2f(x)); + return @floatCast(exp2_f32(x)); } -pub fn exp2f(x: f32) callconv(.c) f32 { +fn exp2f(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(exp2_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn exp2_f32(x: f32) f32 { const tblsiz: u32 = @intCast(exp2ft.len); const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz)); const P1: f32 = 0x1.62e430p-1; @@ -88,7 +94,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 { return @floatCast(r * uk); } -pub fn exp2(x: f64) callconv(.c) f64 { +fn exp2(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(exp2_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn exp2_f64(x: f64) f64 { const tblsiz: u32 = @intCast(exp2dt.len / 2); const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz)); const P1: f64 = 0x1.62e42fefa39efp-1; @@ -156,19 +165,25 @@ pub fn exp2(x: f64) callconv(.c) f64 { return math.scalbn(r, ik); } -pub fn __exp2x(x: f80) callconv(.c) f80 { +fn __exp2x(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(exp2_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn exp2_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(exp2q(x)); + return @floatCast(exp2_f128(x)); } -pub const exp2q = @import("exp_f128.zig").exp2; +fn exp2q(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(exp2_f128(compiler_rt.f128.fromAbi(x))); +} +pub const exp2_f128 = @import("exp_f128.zig").exp2; pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return exp2(x), - 80 => return __exp2x(x), - 128 => return exp2q(x), - else => @compileError("unreachable"), + 64 => return exp2_f64(x), + 80 => return exp2_f80(x), + 128 => return exp2_f128(x), + else => comptime unreachable, } } @@ -452,77 +467,77 @@ const exp2dt = [_]f64{ }; test "exp2f() special" { - try expectEqual(exp2f(0.0), 1.0); - try expectEqual(exp2f(-0.0), 1.0); - try expectEqual(exp2f(1.0), 2.0); - try expectEqual(exp2f(-1.0), 0.5); - try expectEqual(exp2f(math.inf(f32)), math.inf(f32)); - try expect(math.isPositiveZero(exp2f(-math.inf(f32)))); - try expect(math.isNan(exp2f(math.nan(f32)))); - try expect(math.isNan(exp2f(math.snan(f32)))); + try expectEqual(exp2_f32(0.0), 1.0); + try expectEqual(exp2_f32(-0.0), 1.0); + try expectEqual(exp2_f32(1.0), 2.0); + try expectEqual(exp2_f32(-1.0), 0.5); + try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isPositiveZero(exp2_f32(-math.inf(f32)))); + try expect(math.isNan(exp2_f32(math.nan(f32)))); + try expect(math.isNan(exp2_f32(math.snan(f32)))); } test "exp2f() sanity" { - try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9); - try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4); - try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9); - try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7); - try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9); - try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0); - try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1); - try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0); - try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0); - try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1); + try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9); + try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4); + try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9); + try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7); + try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9); + try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0); + try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1); + try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0); + try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0); + try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1); } test "exp2f() boundary" { - try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite - try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result - try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero - try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero - try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal - try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal - try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value - try expectEqual(exp2f(0x1p-149), 1); // Min positive input value - try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value - try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input - try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input + try expectEqual(exp2_f32(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite + try expectEqual(exp2_f32(0x1p+7), math.inf(f32)); // The first value that gives infinite result + try expectEqual(exp2_f32(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero + try expectEqual(exp2_f32(-0x1.2cp+7), 0); // The first value at which the result flushes to zero + try expectEqual(exp2_f32(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal + try expectEqual(exp2_f32(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal + try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value + try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value + try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value + try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input + try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input } test "exp2() special" { - try expectEqual(exp2(0.0), 1.0); - try expectEqual(exp2(-0.0), 1.0); - try expectEqual(exp2(1.0), 2.0); - try expectEqual(exp2(-1.0), 0.5); - try expectEqual(exp2(math.inf(f64)), math.inf(f64)); - try expect(math.isPositiveZero(exp2(-math.inf(f64)))); - try expect(math.isNan(exp2(math.nan(f64)))); - try expect(math.isNan(exp2(math.snan(f64)))); + try expectEqual(exp2_f64(0.0), 1.0); + try expectEqual(exp2_f64(-0.0), 1.0); + try expectEqual(exp2_f64(1.0), 2.0); + try expectEqual(exp2_f64(-1.0), 0.5); + try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isPositiveZero(exp2_f64(-math.inf(f64)))); + try expect(math.isNan(exp2_f64(math.nan(f64)))); + try expect(math.isNan(exp2_f64(math.snan(f64)))); } test "exp2() sanity" { - try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); - try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); - try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); - try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); - try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); - try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); - try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); - try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); - try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); - try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); + try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); + try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); + try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); + try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); + try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); + try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); + try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); + try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); + try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); + try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); } test "exp2() boundary" { - try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite - try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result - try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero - try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero - try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal - try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal - try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value - try expectEqual(exp2(0x1p-1074), 1); // Min positive input value - try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value - try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input - try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input + try expectEqual(exp2_f64(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite + try expectEqual(exp2_f64(0x1p+10), math.inf(f64)); // The first value that gives infinite result + try expectEqual(exp2_f64(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero + try expectEqual(exp2_f64(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero + try expectEqual(exp2_f64(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal + try expectEqual(exp2_f64(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal + try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value + try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value + try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value + try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input + try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input } diff --git a/lib/compiler_rt/exp_f128.zig b/lib/compiler_rt/exp_f128.zig index ac09308ff30ee94c46403e4e7cd9f6afd0bea60c..c7a042c2b11edb228cd597eebdefcadbd3b689bd 100644 --- a/lib/compiler_rt/exp_f128.zig +++ b/lib/compiler_rt/exp_f128.zig @@ -26,7 +26,7 @@ const exp_f128 = @This(); const std = @import("std"); const math = std.math; -pub fn exp(x: f128) callconv(.c) f128 { +pub fn exp(x: f128) f128 { if (!math.isFinite(x)) { if (math.isNan(x)) { if (math.isSignalNan(x)) math.raiseInvalid(); @@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 { } /// Computes 2^x -pub fn exp2(x: f128) callconv(.c) f128 { +pub fn exp2(x: f128) f128 { if (!math.isFinite(x)) { if (math.isNan(x)) { if (math.isSignalNan(x)) math.raiseInvalid(); diff --git a/lib/compiler_rt/extenddftf2.zig b/lib/compiler_rt/extenddftf2.zig deleted file mode 100644 index d6267d7d8a93acd5a56d528d803f789a013dced5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extenddftf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const extendf = @import("./extendf.zig").extendf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__extenddftf2, "__extenddfkf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_dtoq, "_Qp_dtoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__extenddftf2, "_Q_dtoq"); - } - symbol(&__extenddftf2, "__extenddftf2"); -} - -pub fn __extenddftf2(a: f64) callconv(.c) f128 { - return extendf(f128, f64, @as(u64, @bitCast(a))); -} - -fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void { - c.* = extendf(f128, f64, @as(u64, @bitCast(a))); -} diff --git a/lib/compiler_rt/extenddfxf2.zig b/lib/compiler_rt/extenddfxf2.zig deleted file mode 100644 index d18195aea357d8fdd8fc26a0d34db798bc06f187..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extenddfxf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extenddfxf2, "__extenddfxf2"); -} - -pub fn __extenddfxf2(a: f64) callconv(.c) f80 { - return extend_f80(f64, @as(u64, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendf.zig b/lib/compiler_rt/extendf.zig index b923e9d25b7fe41a733b0aeb10db9d51b24176df..a0c637b352680a3b1bf1728c662bce3bdb6db91c 100644 --- a/lib/compiler_rt/extendf.zig +++ b/lib/compiler_rt/extendf.zig @@ -1,10 +1,175 @@ const std = @import("std"); -pub inline fn extendf( - comptime dst_t: type, - comptime src_t: type, - a: @Int(.unsigned, @typeInfo(src_t).float.bits), -) dst_t { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + if (compiler_rt.want_aeabi) { + if (compiler_rt.gnu_f16_abi) { + symbol(&__aeabi_h2f, "__gnu_h2f_ieee"); + } else { + symbol(&__aeabi_h2f, "__aeabi_h2f"); + } + } else if (compiler_rt.gnu_f16_abi) { + symbol(&__extendhfsf2, "__gnu_h2f_ieee"); + } + symbol(&__extendhfsf2, "__extendhfsf2"); + symbol(&__extendhfdf2, "__extendhfdf2"); + symbol(&__extendhfxf2, "__extendhfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extendhftf2, "__extendhfkf2"); + } else { + symbol(&__extendhftf2, "__extendhftf2"); + } + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2d, "__aeabi_f2d"); + } else { + symbol(&__extendsfdf2, "__extendsfdf2"); + } + symbol(&__extendsfxf2, "__extendsfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extendsftf2, "__extendsfkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_stoq, "_Qp_stoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__extendsftf2, "_Q_stoq"); + } else { + symbol(&__extendsftf2, "__extendsftf2"); + } + + symbol(&__extenddfxf2, "__extenddfxf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__extenddftf2, "__extenddfkf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_dtoq, "_Qp_dtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__extenddftf2, "_Q_dtoq"); + } else { + symbol(&__extenddftf2, "__extenddftf2"); + } + + if (compiler_rt.want_ppc_abi) { + symbol(&__extendxftf2, "__extendxfkf2"); + } else { + symbol(&__extendxftf2, "__extendxftf2"); + } +} + +fn __extendhfsf2(a: compiler_rt.f16Conv(f32).Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f16(compiler_rt.f16Conv(f32).fromAbi(a))); +} +fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) u32 { + return @bitCast(f32_floatCast_f16(@bitCast(a))); +} +pub fn f32_floatCast_f16(a: f16) f32 { + return extendf(f32, f16, a); +} + +fn __extendhfdf2(a: compiler_rt.f16Conv(f64).Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f16(compiler_rt.f16Conv(f64).fromAbi(a))); +} +pub fn f64_floatCast_f16(a: f16) f64 { + return extendf(f64, f16, a); +} + +fn __extendhfxf2(a: compiler_rt.f16Conv(f80).Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f16(compiler_rt.f16Conv(f80).fromAbi(a))); +} +pub fn f80_floatCast_f16(a: f16) f80 { + return extend_f80(f16, a); +} + +fn __extendhftf2(a: compiler_rt.f16Conv(f128).Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f16(compiler_rt.f16Conv(f128).fromAbi(a))); +} +pub fn f128_floatCast_f16(a: f16) f128 { + return extendf(f128, f16, a); +} + +fn __extendsfdf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatCast_f32(a); +} +pub fn f64_floatCast_f32(a: f32) f64 { + return extendf(f64, f32, a); +} + +fn __extendsfxf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn f80_floatCast_f32(a: f32) f80 { + return extend_f80(f32, a); +} + +pub fn __extendsftf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void { + c.* = f128_floatCast_f32(a); +} +pub fn f128_floatCast_f32(a: f32) f128 { + return extendf(f128, f32, a); +} + +fn __extenddfxf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn f80_floatCast_f64(a: f64) f80 { + return extend_f80(f64, a); +} + +fn __extenddftf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void { + c.* = f128_floatCast_f64(a); +} +pub fn f128_floatCast_f64(a: f64) f128 { + return extendf(f128, f64, a); +} + +fn __extendxftf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f128_floatCast_f80(a: f80) f128 { + const src_int_bit: u64 = 0x8000000000000000; + const src_sig_mask = ~src_int_bit; + const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit + const dst_sig_bits = std.math.floatMantissaBits(f128); + + const dst_bits = @bitSizeOf(f128); + + // Break a into a sign and representation of the absolute value + var a_rep: std.math.F80 = .fromFloat(a); + const sign = a_rep.exp & 0x8000; + a_rep.exp &= 0x7FFF; + var abs_result: u128 = undefined; + + if (a_rep.exp == 0 and a_rep.fraction == 0) { + // zero + abs_result = 0; + } else if (a_rep.exp == 0x7FFF) { + // a is nan or infinite + abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); + abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; + } else if (a_rep.fraction & src_int_bit != 0) { + // a is a normal value + abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); + abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; + } else { + // a is denormal + abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); + } + + // Apply the signbit to (dst_t)abs(a). + const result: u128 = abs_result | @as(u128, sign) << (dst_bits - 16); + return @bitCast(result); +} + +inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); @@ -31,6 +196,7 @@ pub inline fn extendf( const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; + const a: src_rep_t = @bitCast(f); // Break a into a sign and representation of the absolute value const aRep: src_rep_t = @bitCast(a); const aAbs: src_rep_t = aRep & srcAbsMask; @@ -66,11 +232,11 @@ pub inline fn extendf( } // Apply the signbit to (dst_t)abs(a). - const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); + const result: dst_rep_t = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); return @bitCast(result); } -pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 { +inline fn extend_f80(comptime src_t: type, f: src_t) f80 { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const src_sig_bits = std.math.floatMantissaBits(src_t); const dst_int_bit = 0x8000000000000000; @@ -92,6 +258,7 @@ pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_ var dst: std.math.F80 = undefined; + const a: src_rep_t = @bitCast(f); // Break a into a sign and representation of the absolute value const a_abs = a & src_abs_mask; const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0; diff --git a/lib/compiler_rt/extendf_test.zig b/lib/compiler_rt/extendf_test.zig index f572495b6634f8096fa5dd41dd9d2fd1b362a0a1..4cba105a6dc88b24230e9624d250b05da947edf2 100644 --- a/lib/compiler_rt/extendf_test.zig +++ b/lib/compiler_rt/extendf_test.zig @@ -1,31 +1,37 @@ const builtin = @import("builtin"); - const std = @import("std"); -const math = std.math; +const testing = std.testing; -const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2; -const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2; -const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2; -const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2; -const __extenddfxf2 = @import("extenddfxf2.zig").__extenddfxf2; -const F16T = @import("../compiler_rt.zig").F16T; +const impl = @import("extendf.zig"); -fn test__extenddfxf2(a: f64, expected: u80) !void { - const x = __extenddfxf2(a); +const f32_floatCast_f16 = impl.f32_floatCast_f16; +const f64_floatCast_f16 = impl.f64_floatCast_f16; +const f80_floatCast_f16 = impl.f80_floatCast_f16; +const f128_floatCast_f16 = impl.f128_floatCast_f16; + +const f64_floatCast_f32 = impl.f64_floatCast_f32; +const f80_floatCast_f32 = impl.f80_floatCast_f32; +const f128_floatCast_f32 = impl.f128_floatCast_f32; + +const f80_floatCast_f64 = impl.f80_floatCast_f64; +const f128_floatCast_f64 = impl.f128_floatCast_f64; + +const f128_floatCast_f80 = impl.f128_floatCast_f80; + +fn test_f80_floatCast_f64(a: f64, expected: u80) !void { + const x = f80_floatCast_f64(a); const rep: u80 = @bitCast(x); if (rep == expected) return; - // test other possible NaN representation(signal NaN) - if (math.isNan(@as(f80, @bitCast(expected))) and math.isNan(x)) + if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x)) return; - - @panic("__extenddfxf2 test failure"); + return error.TestFailure; } -fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { - const x = __extenddftf2(a); +fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f64(a); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { if (hi == expected_hi and lo == expected_lo) return; - // test other possible NaN representation(signal NaN) if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and @@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { return; } } - - @panic("__extenddftf2 test failure"); + return error.TestFailure; } -fn test__extendhfsf2(a: u16, expected: u32) !void { - const x = __extendhfsf2(@as(F16T(f32), @bitCast(a))); +fn test_f32_floatCast_f16(a: u16, expected: u32) !void { + const x = f32_floatCast_f16(@bitCast(a)); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void { return; } } - return error.TestFailure; } -fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { - const x = __extendsftf2(a); +fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f32(a); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { if (hi == expected_hi and lo == expected_lo) return; - // test other possible NaN representation(signal NaN) if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and @@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { return; } } - return error.TestFailure; } -test "extenddfxf2" { +test f80_floatCast_f64 { // qNaN - try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000); + try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000); // NaN - try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000); + try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000); // This is bad? // inf - try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000); + try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000); // zero - try test__extenddfxf2(0.0, 0x0); + try test_f80_floatCast_f64(0.0, 0x0); - try test__extenddfxf2(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); + try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); - try test__extenddfxf2(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); + try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); - try test__extenddfxf2(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); + try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); - try test__extenddfxf2(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); + try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); // subnormal - try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800); - try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000); + try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800); + try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000); } -test "extenddftf2" { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - +test f128_floatCast_f64 { // qNaN - try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); + try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0); // NaN - try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); + try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); // inf - try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0); + try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0); // zero - try test__extenddftf2(0.0, 0x0, 0x0); + try test_f128_floatCast_f64(0.0, 0x0, 0x0); - try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); + try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); - try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); + try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); - try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); + try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); - try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); + try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); // subnormal - try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0); - try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0); + try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0); + try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0); } -test "extendhfsf2" { - try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN - try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN +test f32_floatCast_f16 { + try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN + try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN // On x86 the NaN becomes quiet because the return is pushed on the x87 // stack due to ABI requirements if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows) - try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN + try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN - try test__extendhfsf2(0, 0); // 0 - try test__extendhfsf2(0x8000, 0x80000000); // -0 + try test_f32_floatCast_f16(0, 0); // 0 + try test_f32_floatCast_f16(0x8000, 0x80000000); // -0 - try test__extendhfsf2(0x7c00, 0x7f800000); // inf - try test__extendhfsf2(0xfc00, 0xff800000); // -inf + try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf + try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf - try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 - try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 + try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24 + try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24 - try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 - try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 + try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 + try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 - try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 - try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 + try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14 + try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14 - try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 - try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 + try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504 + try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504 - try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 - try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 + try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10 + try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10 - try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 - try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 + try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3 + try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3 } -test "extendsftf2" { +test f128_floatCast_f32 { // qNaN - try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); + try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0); // NaN - try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0); + try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0); // inf - try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0); + try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0); // zero - try test__extendsftf2(0.0, 0x0, 0x0); - try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0); - try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); - try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0); - try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); + try test_f128_floatCast_f32(0.0, 0x0, 0x0); + try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0); + try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); + try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0); + try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); } fn makeQNaN64() f64 { @@ -211,8 +210,8 @@ fn makeInf32() f32 { return @bitCast(@as(u32, 0x7f800000)); } -fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { - const x = __extendhftf2(@as(F16T(f128), @bitCast(a))); +fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatCast_f16(@bitCast(a)); const rep: u128 = @bitCast(x); const hi: u64 = @intCast(rep >> 64); @@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { return error.TestFailure; } -test "extendhftf2" { +test f128_floatCast_f16 { // qNaN - try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0); + try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0); // NaN - try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0); + try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0); // inf - try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0); - try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0); + try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0); + try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0); // zero - try test__extendhftf2(0x0000, 0x0000000000000000, 0x0); - try test__extendhftf2(0x8000, 0x8000000000000000, 0x0); + try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0); + try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0); // denormal - try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0); - try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0); - try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0); + try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0); + try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0); + try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0); // pi - try test__extendhftf2(0x4248, 0x4000920000000000, 0x0); - try test__extendhftf2(0xc248, 0xc000920000000000, 0x0); + try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0); + try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0); - try test__extendhftf2(0x508c, 0x4004230000000000, 0x0); - try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0); + try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0); + try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0); } diff --git a/lib/compiler_rt/extendhfdf2.zig b/lib/compiler_rt/extendhfdf2.zig deleted file mode 100644 index 8cadc7139eebbad29f39b5245a14971c5c187a0d..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfdf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - symbol(&__extendhfdf2, "__extendhfdf2"); -} - -pub fn __extendhfdf2(a: compiler_rt.F16T(f64)) callconv(.c) f64 { - return extendf(f64, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhfsf2.zig b/lib/compiler_rt/extendhfsf2.zig deleted file mode 100644 index b638192c47502e6e698e86fcce8be3fbc0f7d2f9..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfsf2.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const extendf = @import("./extendf.zig").extendf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.gnu_f16_abi) { - symbol(&__gnu_h2f_ieee, "__gnu_h2f_ieee"); - } else if (compiler_rt.want_aeabi) { - symbol(&__aeabi_h2f, "__aeabi_h2f"); - } - symbol(&__extendhfsf2, "__extendhfsf2"); -} - -pub fn __extendhfsf2(a: compiler_rt.F16T(f32)) callconv(.c) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} - -fn __gnu_h2f_ieee(a: compiler_rt.F16T(f32)) callconv(.c) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} - -fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) f32 { - return extendf(f32, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhftf2.zig b/lib/compiler_rt/extendhftf2.zig deleted file mode 100644 index 29e7866b663389aae7048a474e585916fec7cac1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhftf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - symbol(&__extendhftf2, "__extendhftf2"); -} - -pub fn __extendhftf2(a: compiler_rt.F16T(f128)) callconv(.c) f128 { - return extendf(f128, f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendhfxf2.zig b/lib/compiler_rt/extendhfxf2.zig deleted file mode 100644 index e76daf4f55045262daa10cb4547688ed012a6bc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendhfxf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extendhfxf2, "__extendhfxf2"); -} - -fn __extendhfxf2(a: compiler_rt.F16T(f80)) callconv(.c) f80 { - return extend_f80(f16, @as(u16, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsfdf2.zig b/lib/compiler_rt/extendsfdf2.zig deleted file mode 100644 index 4f34b05242a5f57155c9bb83c3e978c6ec3ace42..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsfdf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2d, "__aeabi_f2d"); - } else { - symbol(&__extendsfdf2, "__extendsfdf2"); - } -} - -fn __extendsfdf2(a: f32) callconv(.c) f64 { - return extendf(f64, f32, @as(u32, @bitCast(a))); -} - -fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 { - return extendf(f64, f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsftf2.zig b/lib/compiler_rt/extendsftf2.zig deleted file mode 100644 index 6135065b14297e34c04e7cefec5b9387321089a7..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsftf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const extendf = @import("./extendf.zig").extendf; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__extendsftf2, "__extendsfkf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_stoq, "_Qp_stoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__extendsftf2, "_Q_stoq"); - } - symbol(&__extendsftf2, "__extendsftf2"); -} - -pub fn __extendsftf2(a: f32) callconv(.c) f128 { - return extendf(f128, f32, @as(u32, @bitCast(a))); -} - -fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void { - c.* = extendf(f128, f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendsfxf2.zig b/lib/compiler_rt/extendsfxf2.zig deleted file mode 100644 index 9a6796bd668602b1d653a6581613fcb69edb7853..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendsfxf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const extend_f80 = @import("./extendf.zig").extend_f80; - -comptime { - symbol(&__extendsfxf2, "__extendsfxf2"); -} - -fn __extendsfxf2(a: f32) callconv(.c) f80 { - return extend_f80(f32, @as(u32, @bitCast(a))); -} diff --git a/lib/compiler_rt/extendxftf2.zig b/lib/compiler_rt/extendxftf2.zig deleted file mode 100644 index 1c39e1e84c7a3beb0a9470a123c05dea456eed77..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/extendxftf2.zig +++ /dev/null @@ -1,42 +0,0 @@ -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__extendxftf2, "__extendxftf2"); -} - -fn __extendxftf2(a: f80) callconv(.c) f128 { - const src_int_bit: u64 = 0x8000000000000000; - const src_sig_mask = ~src_int_bit; - const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit - const dst_sig_bits = std.math.floatMantissaBits(f128); - - const dst_bits = @bitSizeOf(f128); - - // Break a into a sign and representation of the absolute value - var a_rep = std.math.F80.fromFloat(a); - const sign = a_rep.exp & 0x8000; - a_rep.exp &= 0x7FFF; - var abs_result: u128 = undefined; - - if (a_rep.exp == 0 and a_rep.fraction == 0) { - // zero - abs_result = 0; - } else if (a_rep.exp == 0x7FFF) { - // a is nan or infinite - abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); - abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; - } else if (a_rep.fraction & src_int_bit != 0) { - // a is a normal value - abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); - abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; - } else { - // a is denormal - abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); - } - - // Apply the signbit to (dst_t)abs(a). - const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16); - return @bitCast(result); -} diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index abdf21df8f33de1c080aba1452ae233287283540..50d2cc17d590a11615bdc471e6926af6c1f7bc6c 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -16,32 +16,47 @@ comptime { symbol(&fabsl, "fabsl"); } -pub fn __fabsh(a: f16) callconv(.c) f16 { +fn __fabsh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fabs_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn fabs_f16(a: f16) f16 { return generic_fabs(a); } -pub fn fabsf(a: f32) callconv(.c) f32 { +fn fabsf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fabs_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn fabs_f32(a: f32) f32 { return generic_fabs(a); } -pub fn fabs(a: f64) callconv(.c) f64 { +fn fabs(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fabs_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn fabs_f64(a: f64) f64 { return generic_fabs(a); } -pub fn __fabsx(a: f80) callconv(.c) f80 { +fn __fabsx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fabs_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn fabs_f80(a: f80) f80 { return generic_fabs(a); } -pub fn fabsq(a: f128) callconv(.c) f128 { +fn fabsq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fabs_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn fabs_f128(a: f128) f128 { return generic_fabs(a); } pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fabs(x), - 80 => return __fabsx(x), - 128 => return fabsq(x), - else => @compileError("unreachable"), + 64 => return fabs_f64(x), + 80 => return fabs_f80(x), + 128 => return fabs_f128(x), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fixdfdi.zig b/lib/compiler_rt/fixdfdi.zig deleted file mode 100644 index 5a66cc124f0f4ec092f1c49715ae6c547a396b66..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2lz, "__aeabi_d2lz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixdfdi, "__dtoi64"); - } - symbol(&__fixdfdi, "__fixdfdi"); - } -} - -pub fn __fixdfdi(a: f64) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixdfei.zig b/lib/compiler_rt/fixdfei.zig deleted file mode 100644 index 170b4a160337fe5fc426fe2e715ab46426d76d7e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixdfei, "__fixdfei"); -} - -pub fn __fixdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixdfsi.zig b/lib/compiler_rt/fixdfsi.zig deleted file mode 100644 index 1d42337ea54573e4c7423147323046b029f9af52..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2iz, "__aeabi_d2iz"); - } else { - symbol(&__fixdfsi, "__fixdfsi"); - } -} - -pub fn __fixdfsi(a: f64) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/fixdfti.zig b/lib/compiler_rt/fixdfti.zig deleted file mode 100644 index ff7434d63da148afc20b22bbfb54d6c1bdd17822..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixdfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixdfti, "__fixdfti"); -} - -pub fn __fixdfti(a: f64) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixhfei.zig b/lib/compiler_rt/fixhfei.zig deleted file mode 100644 index 5b759c3fc683d909ce7808242a59129c310bbb56..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixhfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixhfei, "__fixhfei"); -} - -pub fn __fixhfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixint_test.zig b/lib/compiler_rt/fixint_test.zig deleted file mode 100644 index 198167ab867c22ed6160e83ed90920a6c5e97f28..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixint_test.zig +++ /dev/null @@ -1,149 +0,0 @@ -const std = @import("std"); -const math = std.math; -const testing = std.testing; - -const fixint = @import("fixint.zig").fixint; - -fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) !void { - const x = fixint(fp_t, fixint_t, a); - try testing.expect(x == expected); -} - -test "fixint.i1" { - try test__fixint(f32, i1, -math.inf(f32), -1); - try test__fixint(f32, i1, -math.floatMax(f32), -1); - try test__fixint(f32, i1, -2.0, -1); - try test__fixint(f32, i1, -1.1, -1); - try test__fixint(f32, i1, -1.0, -1); - try test__fixint(f32, i1, -0.9, 0); - try test__fixint(f32, i1, -0.1, 0); - try test__fixint(f32, i1, -math.floatMin(f32), 0); - try test__fixint(f32, i1, -0.0, 0); - try test__fixint(f32, i1, 0.0, 0); - try test__fixint(f32, i1, math.floatMin(f32), 0); - try test__fixint(f32, i1, 0.1, 0); - try test__fixint(f32, i1, 0.9, 0); - try test__fixint(f32, i1, 1.0, 0); - try test__fixint(f32, i1, 2.0, 0); - try test__fixint(f32, i1, math.floatMax(f32), 0); - try test__fixint(f32, i1, math.inf(f32), 0); -} - -test "fixint.i2" { - try test__fixint(f32, i2, -math.inf(f32), -2); - try test__fixint(f32, i2, -math.floatMax(f32), -2); - try test__fixint(f32, i2, -2.0, -2); - try test__fixint(f32, i2, -1.9, -1); - try test__fixint(f32, i2, -1.1, -1); - try test__fixint(f32, i2, -1.0, -1); - try test__fixint(f32, i2, -0.9, 0); - try test__fixint(f32, i2, -0.1, 0); - try test__fixint(f32, i2, -math.floatMin(f32), 0); - try test__fixint(f32, i2, -0.0, 0); - try test__fixint(f32, i2, 0.0, 0); - try test__fixint(f32, i2, math.floatMin(f32), 0); - try test__fixint(f32, i2, 0.1, 0); - try test__fixint(f32, i2, 0.9, 0); - try test__fixint(f32, i2, 1.0, 1); - try test__fixint(f32, i2, 2.0, 1); - try test__fixint(f32, i2, math.floatMax(f32), 1); - try test__fixint(f32, i2, math.inf(f32), 1); -} - -test "fixint.i3" { - try test__fixint(f32, i3, -math.inf(f32), -4); - try test__fixint(f32, i3, -math.floatMax(f32), -4); - try test__fixint(f32, i3, -4.0, -4); - try test__fixint(f32, i3, -3.0, -3); - try test__fixint(f32, i3, -2.0, -2); - try test__fixint(f32, i3, -1.9, -1); - try test__fixint(f32, i3, -1.1, -1); - try test__fixint(f32, i3, -1.0, -1); - try test__fixint(f32, i3, -0.9, 0); - try test__fixint(f32, i3, -0.1, 0); - try test__fixint(f32, i3, -math.floatMin(f32), 0); - try test__fixint(f32, i3, -0.0, 0); - try test__fixint(f32, i3, 0.0, 0); - try test__fixint(f32, i3, math.floatMin(f32), 0); - try test__fixint(f32, i3, 0.1, 0); - try test__fixint(f32, i3, 0.9, 0); - try test__fixint(f32, i3, 1.0, 1); - try test__fixint(f32, i3, 2.0, 2); - try test__fixint(f32, i3, 3.0, 3); - try test__fixint(f32, i3, 4.0, 3); - try test__fixint(f32, i3, math.floatMax(f32), 3); - try test__fixint(f32, i3, math.inf(f32), 3); -} - -test "fixint.i32" { - try test__fixint(f64, i32, -math.inf(f64), math.minInt(i32)); - try test__fixint(f64, i32, -math.floatMax(f64), math.minInt(i32)); - try test__fixint(f64, i32, @as(f64, math.minInt(i32)), math.minInt(i32)); - try test__fixint(f64, i32, @as(f64, math.minInt(i32)) + 1, math.minInt(i32) + 1); - try test__fixint(f64, i32, -2.0, -2); - try test__fixint(f64, i32, -1.9, -1); - try test__fixint(f64, i32, -1.1, -1); - try test__fixint(f64, i32, -1.0, -1); - try test__fixint(f64, i32, -0.9, 0); - try test__fixint(f64, i32, -0.1, 0); - try test__fixint(f64, i32, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i32, -0.0, 0); - try test__fixint(f64, i32, 0.0, 0); - try test__fixint(f64, i32, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i32, 0.1, 0); - try test__fixint(f64, i32, 0.9, 0); - try test__fixint(f64, i32, 1.0, 1); - try test__fixint(f64, i32, @as(f64, math.maxInt(i32)) - 1, math.maxInt(i32) - 1); - try test__fixint(f64, i32, @as(f64, math.maxInt(i32)), math.maxInt(i32)); - try test__fixint(f64, i32, math.floatMax(f64), math.maxInt(i32)); - try test__fixint(f64, i32, math.inf(f64), math.maxInt(i32)); -} - -test "fixint.i64" { - try test__fixint(f64, i64, -math.inf(f64), math.minInt(i64)); - try test__fixint(f64, i64, -math.floatMax(f64), math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64)), math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64)) + 1, math.minInt(i64)); - try test__fixint(f64, i64, @as(f64, math.minInt(i64) / 2), math.minInt(i64) / 2); - try test__fixint(f64, i64, -2.0, -2); - try test__fixint(f64, i64, -1.9, -1); - try test__fixint(f64, i64, -1.1, -1); - try test__fixint(f64, i64, -1.0, -1); - try test__fixint(f64, i64, -0.9, 0); - try test__fixint(f64, i64, -0.1, 0); - try test__fixint(f64, i64, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i64, -0.0, 0); - try test__fixint(f64, i64, 0.0, 0); - try test__fixint(f64, i64, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i64, 0.1, 0); - try test__fixint(f64, i64, 0.9, 0); - try test__fixint(f64, i64, 1.0, 1); - try test__fixint(f64, i64, @as(f64, math.maxInt(i64)) - 1, math.maxInt(i64)); - try test__fixint(f64, i64, @as(f64, math.maxInt(i64)), math.maxInt(i64)); - try test__fixint(f64, i64, math.floatMax(f64), math.maxInt(i64)); - try test__fixint(f64, i64, math.inf(f64), math.maxInt(i64)); -} - -test "fixint.i128" { - try test__fixint(f64, i128, -math.inf(f64), math.minInt(i128)); - try test__fixint(f64, i128, -math.floatMax(f64), math.minInt(i128)); - try test__fixint(f64, i128, @as(f64, math.minInt(i128)), math.minInt(i128)); - try test__fixint(f64, i128, @as(f64, math.minInt(i128)) + 1, math.minInt(i128)); - try test__fixint(f64, i128, -2.0, -2); - try test__fixint(f64, i128, -1.9, -1); - try test__fixint(f64, i128, -1.1, -1); - try test__fixint(f64, i128, -1.0, -1); - try test__fixint(f64, i128, -0.9, 0); - try test__fixint(f64, i128, -0.1, 0); - try test__fixint(f64, i128, -@as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i128, -0.0, 0); - try test__fixint(f64, i128, 0.0, 0); - try test__fixint(f64, i128, @as(f64, math.floatMin(f32)), 0); - try test__fixint(f64, i128, 0.1, 0); - try test__fixint(f64, i128, 0.9, 0); - try test__fixint(f64, i128, 1.0, 1); - try test__fixint(f64, i128, @as(f64, math.maxInt(i128)) - 1, math.maxInt(i128)); - try test__fixint(f64, i128, @as(f64, math.maxInt(i128)), math.maxInt(i128)); - try test__fixint(f64, i128, math.floatMax(f64), math.maxInt(i128)); - try test__fixint(f64, i128, math.inf(f64), math.maxInt(i128)); -} diff --git a/lib/compiler_rt/fixsfdi.zig b/lib/compiler_rt/fixsfdi.zig deleted file mode 100644 index 0a3731877e8bf7c7591391c8d76a6a5f953e74f1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2lz, "__aeabi_f2lz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixsfdi, "__stoi64"); - } - symbol(&__fixsfdi, "__fixsfdi"); - } -} - -pub fn __fixsfdi(a: f32) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixsfei.zig b/lib/compiler_rt/fixsfei.zig deleted file mode 100644 index 43243254059d78d0ba678bcf1ae9ab37b50c3f47..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixsfei, "__fixsfei"); -} - -pub fn __fixsfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixsfsi.zig b/lib/compiler_rt/fixsfsi.zig deleted file mode 100644 index 9c07c5824a25aac5f83ae2e2f58ce4df66f53b38..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2iz, "__aeabi_f2iz"); - } else { - symbol(&__fixsfsi, "__fixsfsi"); - } -} - -pub fn __fixsfsi(a: f32) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/fixsfti.zig b/lib/compiler_rt/fixsfti.zig deleted file mode 100644 index 121eff084d58a00726ed140a0d4f4cacafdce87b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixsfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixsfti, "__fixsfti"); -} - -pub fn __fixsfti(a: f32) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixtfdi.zig b/lib/compiler_rt/fixtfdi.zig deleted file mode 100644 index d64682db1c1153d982acba2636b39f2b17e63753..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfdi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixtfdi, "__fixkfdi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtox, "_Qp_qtox"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixtfdi, "_Q_qtoll"); - } - symbol(&__fixtfdi, "__fixtfdi"); -} - -pub fn __fixtfdi(a: f128) callconv(.c) i64 { - return intFromFloat(i64, a); -} - -fn _Qp_qtox(a: *const f128) callconv(.c) i64 { - return intFromFloat(i64, a.*); -} diff --git a/lib/compiler_rt/fixtfei.zig b/lib/compiler_rt/fixtfei.zig deleted file mode 100644 index 6443a0cb3be226c25affb17567fa8c860868aaa1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixtfei, "__fixtfei"); -} - -pub fn __fixtfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixtfsi.zig b/lib/compiler_rt/fixtfsi.zig deleted file mode 100644 index 9acc5ec8eac8cb72a826c50d6d034e1ea48ef603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfsi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixtfsi, "__fixkfsi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoi, "_Qp_qtoi"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixtfsi, "_Q_qtoi"); - } - symbol(&__fixtfsi, "__fixtfsi"); -} - -pub fn __fixtfsi(a: f128) callconv(.c) i32 { - return intFromFloat(i32, a); -} - -fn _Qp_qtoi(a: *const f128) callconv(.c) i32 { - return intFromFloat(i32, a.*); -} diff --git a/lib/compiler_rt/fixtfti.zig b/lib/compiler_rt/fixtfti.zig deleted file mode 100644 index 0aac298ca2c4d0fa3f8d7fd02cf1290f98929c2b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixtfti.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__fixtfti, "__fixkfti"); - symbol(&__fixtfti, "__fixtfti"); -} - -pub fn __fixtfti(a: f128) callconv(.c) i128 { - return intFromFloat(i128, a); -} diff --git a/lib/compiler_rt/fixunsdfdi.zig b/lib/compiler_rt/fixunsdfdi.zig deleted file mode 100644 index 340bb8f6b11276fd9fff401b7f6a655e63d0a218..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2ulz, "__aeabi_d2ulz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixunsdfdi, "__dtou64"); - } - symbol(&__fixunsdfdi, "__fixunsdfdi"); - } -} - -pub fn __fixunsdfdi(a: f64) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunsdfei.zig b/lib/compiler_rt/fixunsdfei.zig deleted file mode 100644 index f564f7f7a32869e7cdad92a2f264941a3eab7511..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunsdfei, "__fixunsdfei"); -} - -pub fn __fixunsdfei(r: [*]u8, bits: usize, a: f64) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunsdfsi.zig b/lib/compiler_rt/fixunsdfsi.zig deleted file mode 100644 index e8b976d03d690d0de88d07e3fe4b97c0490e5901..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2uiz, "__aeabi_d2uiz"); - } else { - symbol(&__fixunsdfsi, "__fixunsdfsi"); - } -} - -pub fn __fixunsdfsi(a: f64) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunsdfti.zig b/lib/compiler_rt/fixunsdfti.zig deleted file mode 100644 index 1a634baaf5a6da399abaebb3e236ea5c02005ead..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsdfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsdfti, "__fixunsdfti"); -} - -pub fn __fixunsdfti(a: f64) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunshfdi.zig b/lib/compiler_rt/fixunshfdi.zig deleted file mode 100644 index 741e482506d2df3ffbb1388a9848f9317f6f1808..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunshfdi, "__fixunshfdi"); -} - -fn __fixunshfdi(a: f16) callconv(.c) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunshfei.zig b/lib/compiler_rt/fixunshfei.zig deleted file mode 100644 index a61d94f3958f4cc8f5f01f57f317e5a44f32fc20..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunshfei, "__fixunshfei"); -} - -pub fn __fixunshfei(r: [*]u8, bits: usize, a: f16) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunshfsi.zig b/lib/compiler_rt/fixunshfsi.zig deleted file mode 100644 index 438767c7a89a57c22385a1b666a6f59875d1f7ba..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunshfsi, "__fixunshfsi"); -} - -fn __fixunshfsi(a: f16) callconv(.c) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunshfti.zig b/lib/compiler_rt/fixunshfti.zig deleted file mode 100644 index 3dc7a5f99390d05606bb09298651e1d4482e3ab6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunshfti.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunshfti, "__fixunshfti"); -} - -pub fn __fixunshfti(a: f16) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunssfdi.zig b/lib/compiler_rt/fixunssfdi.zig deleted file mode 100644 index ffc238a53fb9f12a64446371a3d3191331d6994c..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfdi.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2ulz, "__aeabi_f2ulz"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__fixunssfdi, "__stou64"); - } - symbol(&__fixunssfdi, "__fixunssfdi"); - } -} - -pub fn __fixunssfdi(a: f32) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunssfei.zig b/lib/compiler_rt/fixunssfei.zig deleted file mode 100644 index 2fd123bd1b4693f96b51604a794dc2879660dc87..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunssfei, "__fixunssfei"); -} - -pub fn __fixunssfei(r: [*]u8, bits: usize, a: f32) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunssfsi.zig b/lib/compiler_rt/fixunssfsi.zig deleted file mode 100644 index f9c09b3f3d881774c21117e3c32b3a0b0b0a9f82..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfsi.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2uiz, "__aeabi_f2uiz"); - } else { - symbol(&__fixunssfsi, "__fixunssfsi"); - } -} - -pub fn __fixunssfsi(a: f32) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunssfti.zig b/lib/compiler_rt/fixunssfti.zig deleted file mode 100644 index 6824afcde4b518642189696a47c0983047dd47c3..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunssfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunssfti, "__fixunssfti"); -} - -pub fn __fixunssfti(a: f32) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunstfdi.zig b/lib/compiler_rt/fixunstfdi.zig deleted file mode 100644 index c535bcc3583c93721f4fc07146f66edcc7611b01..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfdi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixunstfdi, "__fixunskfdi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoux, "_Qp_qtoux"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixunstfdi, "_Q_qtoull"); - } - symbol(&__fixunstfdi, "__fixunstfdi"); -} - -pub fn __fixunstfdi(a: f128) callconv(.c) u64 { - return intFromFloat(u64, a); -} - -fn _Qp_qtoux(a: *const f128) callconv(.c) u64 { - return intFromFloat(u64, a.*); -} diff --git a/lib/compiler_rt/fixunstfei.zig b/lib/compiler_rt/fixunstfei.zig deleted file mode 100644 index 3d8986da90790a1a9cbf9a5fa2939e94c8009cc2..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfei.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunstfei, "__fixunstfei"); -} - -pub fn __fixunstfei(r: [*]u8, bits: usize, a: f128) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunstfsi.zig b/lib/compiler_rt/fixunstfsi.zig deleted file mode 100644 index d31cd759744d7616b30050335f70c50921a76ca9..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfsi.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__fixunstfsi, "__fixunskfsi"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtoui, "_Qp_qtoui"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__fixunstfsi, "_Q_qtou"); - } - symbol(&__fixunstfsi, "__fixunstfsi"); -} - -pub fn __fixunstfsi(a: f128) callconv(.c) u32 { - return intFromFloat(u32, a); -} - -fn _Qp_qtoui(a: *const f128) callconv(.c) u32 { - return intFromFloat(u32, a.*); -} diff --git a/lib/compiler_rt/fixunstfti.zig b/lib/compiler_rt/fixunstfti.zig deleted file mode 100644 index 78c6b1e8f7b90aa5d90a957920e949bb0aa2cbc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunstfti.zig +++ /dev/null @@ -1,14 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__fixunstfti, "__fixunskfti"); - symbol(&__fixunstfti, "__fixunstfti"); -} - -pub fn __fixunstfti(a: f128) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixunsxfdi.zig b/lib/compiler_rt/fixunsxfdi.zig deleted file mode 100644 index 8385961b6b2ea2cd7632776ffa46d41e9e6f8bf3..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const intFromFloat = @import("./int_from_float.zig").intFromFloat; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__fixunsxfdi, "__fixunsxfdi"); -} - -fn __fixunsxfdi(a: f80) callconv(.c) u64 { - return intFromFloat(u64, a); -} diff --git a/lib/compiler_rt/fixunsxfei.zig b/lib/compiler_rt/fixunsxfei.zig deleted file mode 100644 index d7902ddff54773d5240a57c8aaf6910ab6f9f02e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfei.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const symbol = @import("../compiler_rt.zig").symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixunsxfei, "__fixunsxfei"); -} - -pub fn __fixunsxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.unsigned, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixunsxfsi.zig b/lib/compiler_rt/fixunsxfsi.zig deleted file mode 100644 index 7309fbf5a6cf72a7eb862773fbb121437243c2ee..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsxfsi, "__fixunsxfsi"); -} - -fn __fixunsxfsi(a: f80) callconv(.c) u32 { - return intFromFloat(u32, a); -} diff --git a/lib/compiler_rt/fixunsxfti.zig b/lib/compiler_rt/fixunsxfti.zig deleted file mode 100644 index 064c1352c9045870c1a984850f71c86fcf6e8e61..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixunsxfti.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixunsxfti, "__fixunsxfti"); -} - -pub fn __fixunsxfti(a: f80) callconv(.c) u128 { - return intFromFloat(u128, a); -} diff --git a/lib/compiler_rt/fixxfdi.zig b/lib/compiler_rt/fixxfdi.zig deleted file mode 100644 index e9e4b7528b07168dafdf4791a6cc13d795d5b78a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfdi.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixxfdi, "__fixxfdi"); -} - -fn __fixxfdi(a: f80) callconv(.c) i64 { - return intFromFloat(i64, a); -} diff --git a/lib/compiler_rt/fixxfei.zig b/lib/compiler_rt/fixxfei.zig deleted file mode 100644 index 82cd67648df13ac446de3a74ef796ba55ad45065..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfei.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; - -comptime { - symbol(&__fixxfei, "__fixxfei"); -} - -pub fn __fixxfei(r: [*]u8, bits: usize, a: f80) callconv(.c) void { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return bigIntFromFloat(.signed, @ptrCast(@alignCast(r[0..byte_size])), a); -} diff --git a/lib/compiler_rt/fixxfsi.zig b/lib/compiler_rt/fixxfsi.zig deleted file mode 100644 index 363492168c760bcd12432e7c757ec4b8f60a2cc1..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/fixxfsi.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const intFromFloat = @import("./int_from_float.zig").intFromFloat; - -comptime { - symbol(&__fixxfsi, "__fixxfsi"); -} - -fn __fixxfsi(a: f80) callconv(.c) i32 { - return intFromFloat(i32, a); -} diff --git a/lib/compiler_rt/float_from_int.zig b/lib/compiler_rt/float_from_int.zig index 548d027accbb674e1ecbaeb77ef01a5491e256bc..898f246579c2902f5267d7e54c87422292931891 100644 --- a/lib/compiler_rt/float_from_int.zig +++ b/lib/compiler_rt/float_from_int.zig @@ -1,7 +1,475 @@ +const builtin = @import("builtin"); const std = @import("std"); const math = std.math; -pub fn floatFromInt(comptime T: type, x: anytype) T { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + symbol(&__floatsihf, "__floatsihf"); + symbol(&__floatdihf, "__floatdihf"); + symbol(&__floattihf, "__floattihf"); + symbol(&__floateihf, "__floateihf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_i2f, "__aeabi_i2f"); + symbol(&__aeabi_l2f, "__aeabi_l2f"); + } else { + symbol(&__floatsisf, "__floatsisf"); + symbol(&__floatdisf, "__floatdisf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatdisf, "__i64tos"); + } + symbol(&__floattisf, "__floattisf"); + symbol(&__floateisf, "__floateisf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_i2d, "__aeabi_i2d"); + symbol(&__aeabi_l2d, "__aeabi_l2d"); + } else { + symbol(&__floatsidf, "__floatsidf"); + symbol(&__floatdidf, "__floatdidf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatdidf, "__i64tod"); + } + symbol(&__floattidf, "__floattidf"); + symbol(&__floateidf, "__floateidf"); + + symbol(&__floatsixf, "__floatsixf"); + symbol(&__floatdixf, "__floatdixf"); + symbol(&__floattixf, "__floattixf"); + symbol(&__floateixf, "__floateixf"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__floatsitf, "__floatsikf"); + symbol(&__floatditf, "__floatdikf"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_itoq, "_Qp_itoq"); + symbol(&_Qp_xtoq, "_Qp_xtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__floatsitf, "_Q_itoq"); + symbol(&__floatditf, "_Q_lltoq"); + } else { + symbol(&__floatsitf, "__floatsitf"); + symbol(&__floatditf, "__floatditf"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__floattitf, "__floattikf"); + symbol(&__floateitf, "__floateikf"); + } else { + if (builtin.cpu.arch == .x86) { + symbol(&__floattitf_x86, "__floattitf"); + } else { + symbol(&__floattitf, "__floattitf"); + } + symbol(&__floateitf, "__floateitf"); + } +} + +fn __floatsihf(a: i32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i32(a)); +} +pub fn f16_floatFromInt_i32(a: i32) f16 { + return floatFromInt(f16, a); +} + +fn __floatdihf(a: i64) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i64(a)); +} +pub fn f16_floatFromInt_i64(a: i64) f16 { + return floatFromInt(f16, a); +} + +fn __floattihf(a: i128) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_i128(a)); +} +pub fn f16_floatFromInt_i128(a: i128) f16 { + return floatFromInt(f16, a); +} + +fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f16.toAbi(f16_floatFromInt_signed(a[0..byte_size])); +} +pub fn f16_floatFromInt_signed(a: []const u8) f16 { + return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsisf(a: i32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i32(a)); +} +fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_i32(a); +} +pub fn f32_floatFromInt_i32(a: i32) f32 { + return floatFromInt(f32, a); +} + +fn __floatdisf(a: i64) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i64(a)); +} +fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_i64(a); +} +pub fn f32_floatFromInt_i64(a: i64) f32 { + return floatFromInt(f32, a); +} + +fn __floattisf(a: i128) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_i128(a)); +} +pub fn f32_floatFromInt_i128(a: i128) f32 { + return floatFromInt(f32, a); +} + +fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f32.toAbi(f32_floatFromInt_signed(a[0..byte_size])); +} +pub fn f32_floatFromInt_signed(a: []const u8) f32 { + return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsidf(a: i32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i32(a)); +} +fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_i32(a); +} +pub fn f64_floatFromInt_i32(a: i32) f64 { + return floatFromInt(f64, a); +} + +fn __floatdidf(a: i64) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i64(a)); +} +fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_i64(a); +} +pub fn f64_floatFromInt_i64(a: i64) f64 { + return floatFromInt(f64, a); +} + +fn __floattidf(a: i128) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_i128(a)); +} +pub fn f64_floatFromInt_i128(a: i128) f64 { + return floatFromInt(f64, a); +} + +fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f64.toAbi(f64_floatFromInt_signed(a[0..byte_size])); +} +pub fn f64_floatFromInt_signed(a: []const u8) f64 { + return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsixf(a: i32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i32(a)); +} +pub fn f80_floatFromInt_i32(a: i32) f80 { + return floatFromInt(f80, a); +} + +fn __floatdixf(a: i64) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i64(a)); +} +pub fn f80_floatFromInt_i64(a: i64) f80 { + return floatFromInt(f80, a); +} + +fn __floattixf(a: i128) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_i128(a)); +} +pub fn f80_floatFromInt_i128(a: i128) f80 { + return floatFromInt(f80, a); +} + +fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f80.toAbi(f80_floatFromInt_signed(a[0..byte_size])); +} +pub fn f80_floatFromInt_signed(a: []const u8) f80 { + return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a))); +} + +fn __floatsitf(a: i32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i32(a)); +} +fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void { + c.* = f128_floatFromInt_i32(a); +} +pub fn f128_floatFromInt_i32(a: i32) f128 { + return floatFromInt(f128, a); +} + +fn __floatditf(a: i64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i64(a)); +} +fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void { + c.* = f128_floatFromInt_i64(a); +} +pub fn f128_floatFromInt_i64(a: i64) f128 { + return floatFromInt(f128, a); +} + +fn __floattitf(a: i128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i128(a)); +} +fn __floattitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_i128(@bitCast(a))); +} +pub fn f128_floatFromInt_i128(a: i128) f128 { + return floatFromInt(f128, a); +} + +fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f128.toAbi(f128_floatFromInt_signed(a[0..byte_size])); +} +pub fn f128_floatFromInt_signed(a: []const u8) f128 { + return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a))); +} + +comptime { + symbol(&__floatunsihf, "__floatunsihf"); + symbol(&__floatundihf, "__floatundihf"); + symbol(&__floatuntihf, "__floatuntihf"); + symbol(&__floatuneihf, "__floatuneihf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ui2f, "__aeabi_ui2f"); + symbol(&__aeabi_ul2f, "__aeabi_ul2f"); + } else { + symbol(&__floatunsisf, "__floatunsisf"); + symbol(&__floatundisf, "__floatundisf"); + if (compiler_rt.want_windows_arm_abi) symbol(&__floatundisf, "__u64tos"); + } + symbol(&__floatuntisf, "__floatuntisf"); + symbol(&__floatuneisf, "__floatuneisf"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ui2d, "__aeabi_ui2d"); + } else { + symbol(&__floatunsidf, "__floatunsidf"); + } + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_ul2d, "__aeabi_ul2d"); + } else { + if (compiler_rt.want_windows_arm_abi) { + symbol(&__floatundidf, "__u64tod"); + } + symbol(&__floatundidf, "__floatundidf"); + } + symbol(&__floatuntidf, "__floatuntidf"); + symbol(&__floatuneidf, "__floatuneidf"); + + symbol(&__floatunsixf, "__floatunsixf"); + symbol(&__floatundixf, "__floatundixf"); + symbol(&__floatuntixf, "__floatuntixf"); + symbol(&__floatuneixf, "__floatuneixf"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__floatunsitf, "__floatunsikf"); + symbol(&__floatunditf, "__floatundikf"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_uitoq, "_Qp_uitoq"); + symbol(&_Qp_uxtoq, "_Qp_uxtoq"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__floatunsitf, "_Q_utoq"); + symbol(&__floatunditf, "_Q_ulltoq"); + } else { + symbol(&__floatunsitf, "__floatunsitf"); + symbol(&__floatunditf, "__floatunditf"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__floatuntitf, "__floatuntikf"); + symbol(&__floatuneitf, "__floatuneikf"); + } else { + if (builtin.cpu.arch == .x86) { + symbol(&__floatuntitf_x86, "__floatuntitf"); + } else if (builtin.cpu.arch == .x86_64 and + (builtin.os.tag == .windows or builtin.os.tag == .uefi)) + { + symbol(&__floatuntitf_x86_64_windows, "__floatuntitf"); + } else { + symbol(&__floatuntitf, "__floatuntitf"); + } + symbol(&__floatuneitf, "__floatuneitf"); + } +} + +fn __floatunsihf(a: u32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u32(a)); +} +pub fn f16_floatFromInt_u32(a: u32) f16 { + return floatFromInt(f16, a); +} + +fn __floatundihf(a: u64) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u64(a)); +} +pub fn f16_floatFromInt_u64(a: u64) f16 { + return floatFromInt(f16, a); +} + +fn __floatuntihf(a: u128) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(f16_floatFromInt_u128(a)); +} +pub fn f16_floatFromInt_u128(a: u128) f16 { + return floatFromInt(f16, a); +} + +fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f16.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f16.toAbi(f16_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f16_floatFromInt_unsigned(a: []const u8) f16 { + return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsisf(a: u32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u32(a)); +} +fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_u32(a); +} +pub fn f32_floatFromInt_u32(a: u32) f32 { + return floatFromInt(f32, a); +} + +fn __floatundisf(a: u64) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u64(a)); +} +fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatFromInt_u64(a); +} +pub fn f32_floatFromInt_u64(a: u64) f32 { + return floatFromInt(f32, a); +} + +fn __floatuntisf(a: u128) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatFromInt_u128(a)); +} +pub fn f32_floatFromInt_u128(a: u128) f32 { + return floatFromInt(f32, a); +} + +fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f32.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f32.toAbi(f32_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f32_floatFromInt_unsigned(a: []const u8) f32 { + return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsidf(a: u32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u32(a)); +} +fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_u32(a); +} +pub fn f64_floatFromInt_u32(a: u32) f64 { + return floatFromInt(f64, a); +} + +fn __floatundidf(a: u64) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u64(a)); +} +fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 { + return f64_floatFromInt_u64(a); +} +pub fn f64_floatFromInt_u64(a: u64) f64 { + return floatFromInt(f64, a); +} + +fn __floatuntidf(a: u128) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatFromInt_u128(a)); +} +pub fn f64_floatFromInt_u128(a: u128) f64 { + return floatFromInt(f64, a); +} + +fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f64.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f64.toAbi(f64_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f64_floatFromInt_unsigned(a: []const u8) f64 { + return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsixf(a: u32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u32(a)); +} +pub fn f80_floatFromInt_u32(a: u32) f80 { + return floatFromInt(f80, a); +} + +fn __floatundixf(a: u64) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u64(a)); +} +pub fn f80_floatFromInt_u64(a: u64) f80 { + return floatFromInt(f80, a); +} + +fn __floatuntixf(a: u128) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatFromInt_u128(a)); +} +pub fn f80_floatFromInt_u128(a: u128) f80 { + return floatFromInt(f80, a); +} + +fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f80.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f80.toAbi(f80_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f80_floatFromInt_unsigned(a: []const u8) f80 { + return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a))); +} + +fn __floatunsitf(a: u32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u32(a)); +} +fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void { + c.* = f128_floatFromInt_u32(a); +} +pub fn f128_floatFromInt_u32(a: u32) f128 { + return floatFromInt(f128, a); +} + +fn __floatunditf(a: u64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u64(a)); +} +fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void { + c.* = f128_floatFromInt_u64(a); +} +pub fn f128_floatFromInt_u64(a: u64) f128 { + return floatFromInt(f128, a); +} + +fn __floatuntitf(a: u128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(a)); +} +fn __floatuntitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(a))); +} +fn __floatuntitf_x86_64_windows(a_lo: u64, a_hi: u64) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast( + packed struct { lo: u64, hi: u64 }{ .lo = a_lo, .hi = a_hi }, + ))); +} +pub fn f128_floatFromInt_u128(a: u128) f128 { + return floatFromInt(f128, a); +} + +fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) compiler_rt.f128.Abi { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return compiler_rt.f128.toAbi(f128_floatFromInt_unsigned(a[0..byte_size])); +} +pub fn f128_floatFromInt_unsigned(a: []const u8) f128 { + return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a))); +} + +inline fn floatFromInt(comptime T: type, x: anytype) T { if (x == 0) return 0; // Various constants whose values follow from the type parameters. @@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T { return @bitCast(sign_bit | result); } -const endian = @import("builtin").cpu.arch.endian(); +const endian = builtin.cpu.arch.endian(); inline fn limb(limbs: []const u32, index: usize) u32 { return switch (endian) { .little => limbs[index], @@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 { }; } -pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T { +inline fn floatFromBigInt(comptime T: type, comptime signedness: std.lang.Signedness, x: []const u32) T { switch (x.len) { 0 => return 0, inline 1...4 => |limbs_len| { - const low_to_high: [limbs_len]u32 = switch (@import("builtin").cpu.arch.endian()) { + const low_to_high: [limbs_len]u32 = switch (endian) { .little => x[0..limbs_len].*, .big => switch (limbs_len) { 1 => .{x[0]}, diff --git a/lib/compiler_rt/float_from_int_test.zig b/lib/compiler_rt/float_from_int_test.zig index 8c908f420959b28fe107f290cb0bcb709c9ffd85..4ce3129f890f3f303d835733644afcf2fedbff4c 100644 --- a/lib/compiler_rt/float_from_int_test.zig +++ b/lib/compiler_rt/float_from_int_test.zig @@ -2,571 +2,593 @@ const std = @import("std"); const testing = std.testing; const math = std.math; -const __floatunsihf = @import("floatunsihf.zig").__floatunsihf; - -// Conversion to f32 -const __floatsisf = @import("floatsisf.zig").__floatsisf; -const __floatunsisf = @import("floatunsisf.zig").__floatunsisf; -const __floatdisf = @import("floatdisf.zig").__floatdisf; -const __floatundisf = @import("floatundisf.zig").__floatundisf; -const __floattisf = @import("floattisf.zig").__floattisf; -const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; -const __floateisf = @import("floateisf.zig").__floateisf; -const __floatuneisf = @import("floatuneisf.zig").__floatuneisf; - -// Conversion to f64 -const __floatsidf = @import("floatsidf.zig").__floatsidf; -const __floatunsidf = @import("floatunsidf.zig").__floatunsidf; -const __floatdidf = @import("floatdidf.zig").__floatdidf; -const __floatundidf = @import("floatundidf.zig").__floatundidf; -const __floattidf = @import("floattidf.zig").__floattidf; -const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; - -// Conversion to f128 -const __floatsitf = @import("floatsitf.zig").__floatsitf; -const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; -const __floatditf = @import("floatditf.zig").__floatditf; -const __floatunditf = @import("floatunditf.zig").__floatunditf; -const __floattitf = @import("floattitf.zig").__floattitf; -const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; - -fn test__floatsisf(a: i32, expected: u32) !void { - const r = __floatsisf(a); +const impl = @import("float_from_int.zig"); + +const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32; +const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32; +const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64; +const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64; +const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128; +const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128; +const f16_floatFromInt_signed = impl.f16_floatFromInt_signed; +const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned; + +const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32; +const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32; +const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64; +const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64; +const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128; +const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128; +const f32_floatFromInt_signed = impl.f32_floatFromInt_signed; +const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned; + +const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32; +const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32; +const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64; +const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64; +const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128; +const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128; +const f64_floatFromInt_signed = impl.f64_floatFromInt_signed; +const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned; + +const f80_floatFromInt_i32 = impl.f80_floatFromInt_i32; +const f80_floatFromInt_u32 = impl.f80_floatFromInt_u32; +const f80_floatFromInt_i64 = impl.f80_floatFromInt_i64; +const f80_floatFromInt_u64 = impl.f80_floatFromInt_u64; +const f80_floatFromInt_i128 = impl.f80_floatFromInt_i128; +const f80_floatFromInt_u128 = impl.f80_floatFromInt_u128; +const f80_floatFromInt_signed = impl.f80_floatFromInt_signed; +const f80_floatFromInt_unsigned = impl.f80_floatFromInt_unsigned; + +const f128_floatFromInt_i32 = impl.f128_floatFromInt_i32; +const f128_floatFromInt_u32 = impl.f128_floatFromInt_u32; +const f128_floatFromInt_i64 = impl.f128_floatFromInt_i64; +const f128_floatFromInt_u64 = impl.f128_floatFromInt_u64; +const f128_floatFromInt_i128 = impl.f128_floatFromInt_i128; +const f128_floatFromInt_u128 = impl.f128_floatFromInt_u128; +const f128_floatFromInt_signed = impl.f128_floatFromInt_signed; +const f128_floatFromInt_unsigned = impl.f128_floatFromInt_unsigned; + +fn test_f32_floatFromInt_i32(a: i32, expected: u32) !void { + const r = f32_floatFromInt_i32(a); try std.testing.expect(@as(u32, @bitCast(r)) == expected); } -fn test_one_floatunsisf(a: u32, expected: u32) !void { - const r = __floatunsisf(a); +fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void { + const r = f32_floatFromInt_u32(a); try std.testing.expect(@as(u32, @bitCast(r)) == expected); } -test "floatsisf" { - try test__floatsisf(0, 0x00000000); - try test__floatsisf(1, 0x3f800000); - try test__floatsisf(-1, 0xbf800000); - try test__floatsisf(0x7FFFFFFF, 0x4f000000); - try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); +test f32_floatFromInt_i32 { + try test_f32_floatFromInt_i32(0, 0x00000000); + try test_f32_floatFromInt_i32(1, 0x3f800000); + try test_f32_floatFromInt_i32(-1, 0xbf800000); + try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000); + try test_f32_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); + + try testing.expect(f32_floatFromInt_i32(math.minInt(i32)) == math.minInt(i32)); } -test "floatunsisf" { +test f32_floatFromInt_u32 { // Test the produced bit pattern - try test_one_floatunsisf(0, 0); - try test_one_floatunsisf(1, 0x3f800000); - try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); - try test_one_floatunsisf(0x80000000, 0x4f000000); - try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); + try test_f32_floatFromInt_u32(0, 0); + try test_f32_floatFromInt_u32(1, 0x3f800000); + try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000); + try test_f32_floatFromInt_u32(0x80000000, 0x4f000000); + try test_f32_floatFromInt_u32(0xFFFFFFFF, 0x4f800000); + + try testing.expect(f32_floatFromInt_u32(0) == 0.0); + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24)) == math.maxInt(u24)); + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even + try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact + try testing.expect(f32_floatFromInt_u32(math.maxInt(u32)) == math.maxInt(u32) + 1); } -fn test__floatdisf(a: i64, expected: f32) !void { - const x = __floatdisf(a); +fn test_f32_floatFromInt_i64(a: i64, expected: f32) !void { + const x = f32_floatFromInt_i64(a); try testing.expect(x == expected); } -fn test__floatundisf(a: u64, expected: f32) !void { - try std.testing.expectEqual(expected, __floatundisf(a)); +fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void { + const x = f32_floatFromInt_u64(a); + try testing.expect(x == expected); } -test "floatdisf" { - try test__floatdisf(0, 0.0); - try test__floatdisf(1, 1.0); - try test__floatdisf(2, 2.0); - try test__floatdisf(-1, -1.0); - try test__floatdisf(-2, -2.0); - try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); - try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); - try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); - try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); +test f32_floatFromInt_i64 { + try test_f32_floatFromInt_i64(0, 0.0); + try test_f32_floatFromInt_i64(1, 1.0); + try test_f32_floatFromInt_i64(2, 2.0); + try test_f32_floatFromInt_i64(-1, -1.0); + try test_f32_floatFromInt_i64(-2, -2.0); + try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); + try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); + try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50); } -test "floatundisf" { - try test__floatundisf(0, 0.0); - try test__floatundisf(1, 1.0); - try test__floatundisf(2, 2.0); - try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatundisf(0x8000008000000000, 0x1p+63); - try test__floatundisf(0x8000010000000000, 0x1.000002p+63); - try test__floatundisf(0x8000000000000000, 0x1p+63); - try test__floatundisf(0x8000000000000001, 0x1p+63); - try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); - try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); - try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); +test f32_floatFromInt_u64 { + try test_f32_floatFromInt_u64(0, 0.0); + try test_f32_floatFromInt_u64(1, 1.0); + try test_f32_floatFromInt_u64(2, 2.0); + try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63); + try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); + try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63); + try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63); + try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64); + try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64); + try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50); } -fn test__floattisf(a: i128, expected: f32) !void { - const x = __floattisf(a); +fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void { + const x = f32_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntisf(a: u128, expected: f32) !void { - const x = __floatuntisf(a); +fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void { + const x = f32_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattisf" { - try test__floattisf(0, 0.0); +test f32_floatFromInt_i128 { + try test_f32_floatFromInt_i128(0, 0.0); - try test__floattisf(1, 1.0); - try test__floattisf(2, 2.0); - try test__floattisf(-1, -1.0); - try test__floattisf(-2, -2.0); + try test_f32_floatFromInt_i128(1, 1.0); + try test_f32_floatFromInt_i128(2, 2.0); + try test_f32_floatFromInt_i128(-1, -1.0); + try test_f32_floatFromInt_i128(-2, -2.0); - try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); - try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); + try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); - try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); + try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB8p+50); - try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); - try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); - try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); + try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); } -test "floatuntisf" { - try test__floatuntisf(0, 0.0); +test f32_floatFromInt_u128 { + try test_f32_floatFromInt_u128(0, 0.0); - try test__floatuntisf(1, 1.0); - try test__floatuntisf(2, 2.0); - try test__floatuntisf(20, 20.0); + try test_f32_floatFromInt_u128(1, 1.0); + try test_f32_floatFromInt_u128(2, 2.0); + try test_f32_floatFromInt_u128(20, 20.0); - try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); - try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127); - try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); - try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); + try test_f32_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); - try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); - try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); + try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64); + try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0x1p+64); - try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); - try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50); + try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); - try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); + try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50); + try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); - try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); + try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); // Test overflow to infinity - try test__floatuntisf(math.maxInt(u128), @bitCast(math.inf(f32))); + try test_f32_floatFromInt_u128(math.maxInt(u128), @bitCast(math.inf(f32))); } -fn test_floateisf(expected: u32, comptime T: type, a: T) !void { +fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void { const int = @typeInfo(T).int; const r = switch (int.signedness) { - .signed => __floateisf, - .unsigned => __floatuneisf, - }(@ptrCast(&a), int.bits); + .signed => f32_floatFromInt_signed, + .unsigned => f32_floatFromInt_unsigned, + }(@ptrCast(&a)); try testing.expect(expected == @as(u32, @bitCast(r))); } -test "floateisf" { - try test_floateisf(0xFF000000, i256, -1 << 127); - try test_floateisf(0xFF000000, i256, -math.maxInt(u127)); - try test_floateisf(0xDF012347, i256, -0x8123468100000000); - try test_floateisf(0xDF012347, i256, -0x8123468000000001); - try test_floateisf(0xDF012346, i256, -0x8123468000000000); - try test_floateisf(0xDF012346, i256, -0x8123458100000000); - try test_floateisf(0xDF012346, i256, -0x8123458000000001); - try test_floateisf(0xDF012346, i256, -0x8123458000000000); - try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF); - try test_floateisf(0xBF800000, i256, -1); - try test_floateisf(0x00000000, i256, 0); - try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF); - try test_floateisf(0x5F012346, i256, 0x8123458000000000); - try test_floateisf(0x5F012346, i256, 0x8123458000000001); - try test_floateisf(0x5F012346, i256, 0x8123458100000000); - try test_floateisf(0x5F012346, i256, 0x8123468000000000); - try test_floateisf(0x5F012347, i256, 0x8123468000000001); - try test_floateisf(0x5F012347, i256, 0x8123468100000000); - try test_floateisf(0x7F000000, i256, math.maxInt(u127)); - try test_floateisf(0x7F000000, i256, 1 << 127); +test f32_floatFromInt_signed { + try test_f32_floatFromInt(0xFF000000, i256, -1 << 127); + try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127)); + try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000); + try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001); + try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000); + try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF); + try test_f32_floatFromInt(0xBF800000, i256, -1); + try test_f32_floatFromInt(0x00000000, i256, 0); + try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000); + try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000); + try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001); + try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000); + try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127)); + try test_f32_floatFromInt(0x7F000000, i256, 1 << 127); } -test "floatuneisf" { - try test_floateisf(0x00000000, u256, 0); - try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF); - try test_floateisf(0x5F012346, u256, 0x8123458000000000); - try test_floateisf(0x5F012346, u256, 0x8123458000000001); - try test_floateisf(0x5F012346, u256, 0x8123458080000000); - try test_floateisf(0x5F012346, u256, 0x8123468000000000); - try test_floateisf(0x5F012347, u256, 0x8123468000000001); - try test_floateisf(0x5F012347, u256, 0x8123468080000000); - try test_floateisf(0x7F000000, u256, math.maxInt(u127)); - try test_floateisf(0x7F000000, u256, 1 << 127); - try test_floateisf(0x7F800000, u256, math.maxInt(u256)); +test f32_floatFromInt_unsigned { + try test_f32_floatFromInt(0x00000000, u256, 0); + try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000); + try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000); + try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001); + try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000); + try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127)); + try test_f32_floatFromInt(0x7F000000, u256, 1 << 127); + try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256)); } -fn test_one_floatsidf(a: i32, expected: u64) !void { - const r = __floatsidf(a); +fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void { + const r = f64_floatFromInt_i32(a); try std.testing.expect(@as(u64, @bitCast(r)) == expected); } -fn test_one_floatunsidf(a: u32, expected: u64) !void { - const r = __floatunsidf(a); +fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void { + const r = f64_floatFromInt_u32(a); try std.testing.expect(@as(u64, @bitCast(r)) == expected); } -test "floatsidf" { - try test_one_floatsidf(0, 0x0000000000000000); - try test_one_floatsidf(1, 0x3ff0000000000000); - try test_one_floatsidf(-1, 0xbff0000000000000); - try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000); - try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); +test f64_floatFromInt_i32 { + try test_f64_floatFromInt_i32(0, 0x0000000000000000); + try test_f64_floatFromInt_i32(1, 0x3ff0000000000000); + try test_f64_floatFromInt_i32(-1, 0xbff0000000000000); + try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000); + try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); } -test "floatunsidf" { - try test_one_floatunsidf(0, 0x0000000000000000); - try test_one_floatunsidf(1, 0x3ff0000000000000); - try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000); - try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000); - try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000); +test f64_floatFromInt_u32 { + try test_f64_floatFromInt_u32(0, 0x0000000000000000); + try test_f64_floatFromInt_u32(1, 0x3ff0000000000000); + try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000); + try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000); + try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000); } -fn test__floatdidf(a: i64, expected: f64) !void { - const r = __floatdidf(a); +fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void { + const r = f64_floatFromInt_i64(a); try testing.expect(r == expected); } -fn test__floatundidf(a: u64, expected: f64) !void { - const r = __floatundidf(a); +fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void { + const r = f64_floatFromInt_u64(a); try testing.expect(r == expected); } -test "floatdidf" { - try test__floatdidf(0, 0.0); - try test__floatdidf(1, 1.0); - try test__floatdidf(2, 2.0); - try test__floatdidf(20, 20.0); - try test__floatdidf(-1, -1.0); - try test__floatdidf(-2, -2.0); - try test__floatdidf(-20, -20.0); - try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); - try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 - try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); +test f64_floatFromInt_i64 { + try test_f64_floatFromInt_i64(0, 0.0); + try test_f64_floatFromInt_i64(1, 1.0); + try test_f64_floatFromInt_i64(2, 2.0); + try test_f64_floatFromInt_i64(20, 20.0); + try test_f64_floatFromInt_i64(-1, -1.0); + try test_f64_floatFromInt_i64(-2, -2.0); + try test_f64_floatFromInt_i64(-20, -20.0); + try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); + try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 + try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); } -test "floatundidf" { - try test__floatundidf(0, 0.0); - try test__floatundidf(1, 1.0); - try test__floatundidf(2, 2.0); - try test__floatundidf(20, 20.0); - try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatundidf(0x8000008000000000, 0x1.000001p+63); - try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63); - try test__floatundidf(0x8000010000000000, 0x1.000002p+63); - try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63); - try test__floatundidf(0x8000000000000000, 0x1p+63); - try test__floatundidf(0x8000000000000001, 0x1p+63); - try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); +test f64_floatFromInt_u64 { + try test_f64_floatFromInt_u64(0, 0.0); + try test_f64_floatFromInt_u64(1, 1.0); + try test_f64_floatFromInt_u64(2, 2.0); + try test_f64_floatFromInt_u64(20, 20.0); + try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63); + try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63); + try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); + try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63); + try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63); + try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63); + try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); + try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50); + try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); } -fn test__floattidf(a: i128, expected: f64) !void { - const x = __floattidf(a); +fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void { + const x = f64_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntidf(a: u128, expected: f64) !void { - const x = __floatuntidf(a); +fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void { + const x = f64_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattidf" { - try test__floattidf(0, 0.0); - - try test__floattidf(1, 1.0); - try test__floattidf(2, 2.0); - try test__floattidf(20, 20.0); - try test__floattidf(-1, -1.0); - try test__floattidf(-2, -2.0); - try test__floattidf(-20, -20.0); - - try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); - try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); - try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); - try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); - - try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); - try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127); - - try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); - try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); - try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); +test f64_floatFromInt_i128 { + try test_f64_floatFromInt_i128(0, 0.0); + + try test_f64_floatFromInt_i128(1, 1.0); + try test_f64_floatFromInt_i128(2, 2.0); + try test_f64_floatFromInt_i128(20, 20.0); + try test_f64_floatFromInt_i128(-1, -1.0); + try test_f64_floatFromInt_i128(-2, -2.0); + try test_f64_floatFromInt_i128(-20, -20.0); + + try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); + try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); + + try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); + try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127); + + try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); } -test "floatuntidf" { - try test__floatuntidf(0, 0.0); - - try test__floatuntidf(1, 1.0); - try test__floatuntidf(2, 2.0); - try test__floatuntidf(20, 20.0); - - try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); - try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); - try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); - try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); - - try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); - try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); - - try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); - try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); - try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); - try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); - try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); +test f64_floatFromInt_u128 { + try test_f64_floatFromInt_u128(0, 0.0); + + try test_f64_floatFromInt_u128(1, 1.0); + try test_f64_floatFromInt_u128(2, 2.0); + try test_f64_floatFromInt_u128(20, 20.0); + + try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); + + try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); + try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); + + try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); + try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); + try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); } -fn test__floatsitf(a: i32, expected: u128) !void { - const r = __floatsitf(a); +fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void { + const r = f128_floatFromInt_i32(a); try std.testing.expect(@as(u128, @bitCast(r)) == expected); } -test "floatsitf" { - try test__floatsitf(0, 0); - try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); - try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000); - try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000); - try test__floatsitf(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000); - try test__floatsitf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000); -} - -fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { - const x = __floatunsitf(a); +fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatFromInt_u32(a); const x_repr: u128 = @bitCast(x); const x_hi: u64 = @intCast(x_repr >> 64); @@ -581,24 +603,32 @@ fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { return; } } + return error.TestFailure; +} - @panic("__floatunsitf test failure"); +test f128_floatFromInt_i32 { + try test_f128_floatFromInt_i32(0, 0); + try test_f128_floatFromInt_i32(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); + try test_f128_floatFromInt_i32(0x12345678, 0x401b2345678000000000000000000000); + try test_f128_floatFromInt_i32(-0x12345678, 0xc01b2345678000000000000000000000); + try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000); + try test_f128_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000); } -test "floatunsitf" { - try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); - try test__floatunsitf(0, 0x0, 0x0); - try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); - try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); +test f128_floatFromInt_u32 { + try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0); + try test_f128_floatFromInt_u32(0, 0x0, 0x0); + try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0); + try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0); } -fn test__floatditf(a: i64, expected: f128) !void { - const x = __floatditf(a); +fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void { + const x = f128_floatFromInt_i64(a); try testing.expect(x == expected); } -fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { - const x = __floatunditf(a); +fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void { + const x = f128_floatFromInt_u64(a); const x_repr: u128 = @bitCast(x); const x_hi: u64 = @intCast(x_repr >> 64); @@ -613,208 +643,207 @@ fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { return; } } - - @panic("__floatunditf test failure"); + return error.TestFailure; } -test "floatditf" { - try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); - try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); - try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0)); - try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0)); - try test__floatditf(0x0, make_tf(0x0, 0x0)); - try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); - try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); - try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); - try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); +test f128_floatFromInt_i64 { + try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); + try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); + try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0)); + try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0)); + try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); + try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); + try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); } -test "floatunditf" { - try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); - try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); - try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); - try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); - try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); - try test__floatunditf(0x2, 0x4000000000000000, 0x0); - try test__floatunditf(0x1, 0x3fff000000000000, 0x0); - try test__floatunditf(0x0, 0x0, 0x0); +test f128_floatFromInt_u64 { + try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); + try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); + try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0); + try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); + try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); + try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0); + try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0); + try test_f128_floatFromInt_u64(0x0, 0x0, 0x0); } -fn test__floattitf(a: i128, expected: f128) !void { - const x = __floattitf(a); +fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void { + const x = f128_floatFromInt_i128(a); try testing.expect(x == expected); } -fn test__floatuntitf(a: u128, expected: f128) !void { - const x = __floatuntitf(a); +fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void { + const x = f128_floatFromInt_u128(a); try testing.expect(x == expected); } -test "floattitf" { - try test__floattitf(0, 0.0); - - try test__floattitf(1, 1.0); - try test__floattitf(2, 2.0); - try test__floattitf(20, 20.0); - try test__floattitf(-1, -1.0); - try test__floattitf(-2, -2.0); - try test__floattitf(-20, -20.0); - - try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - - try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); - try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); - try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); - try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); - - try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); - try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); - - try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); - try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); - try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); - try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); - try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); - try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); - try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); - try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); - try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); - try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); - try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); - try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); - try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); - try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); - try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); - try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); - try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); - try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); - try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); - try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); - try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); - try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); - try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); - try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); - try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); - try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); - try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); - - try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); - - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); - try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); +test f128_floatFromInt_i128 { + try test_f128_floatFromInt_i128(0, 0.0); + + try test_f128_floatFromInt_i128(1, 1.0); + try test_f128_floatFromInt_i128(2, 2.0); + try test_f128_floatFromInt_i128(20, 20.0); + try test_f128_floatFromInt_i128(-1, -1.0); + try test_f128_floatFromInt_i128(-2, -2.0); + try test_f128_floatFromInt_i128(-20, -20.0); + + try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + + try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); + try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); + + try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); + try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); + + try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); + try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); + try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); + + try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); + + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); + try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); } -test "floatuntitf" { - try test__floatuntitf(0, 0.0); - - try test__floatuntitf(1, 1.0); - try test__floatuntitf(2, 2.0); - try test__floatuntitf(20, 20.0); - - try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); - try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); - try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); - try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); - try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); - try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); - try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); - - try test__floatuntitf(0x8000008000000000, 0x8.000008p+60); - try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60); - try test__floatuntitf(0x8000010000000000, 0x8.00001p+60); - try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60); - - try test__floatuntitf(0x8000000000000000, 0x8p+60); - try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60); - - try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); - - try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); - try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); - try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); - try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); - try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); - - try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); - try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); - try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); - try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); - try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); - - try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); - try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); - try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); - try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); - try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); - try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); - try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); - try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); - try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); - try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); - try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); - try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); - try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); - try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); - try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); - - try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); - try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); - try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); - try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); - - try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); - - try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); - try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); - - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); - try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); +test f128_floatFromInt_u128 { + try test_f128_floatFromInt_u128(0, 0.0); + + try test_f128_floatFromInt_u128(1, 1.0); + try test_f128_floatFromInt_u128(2, 2.0); + try test_f128_floatFromInt_u128(20, 20.0); + + try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); + try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); + try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); + try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); + try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); + + try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60); + try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60); + try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60); + try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60); + + try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60); + try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60); + + try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); + + try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); + try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); + try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); + try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); + try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); + + try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); + try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); + try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); + try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); + try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); + + try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); + try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); + + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); + try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); + + try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); + + try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); + try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); + + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); + try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); } fn make_ti(high: u64, low: u64) i128 { @@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 { return @bitCast(result); } -test "conversion to f16" { - try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0); - try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0); - try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504); - try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16)); +test f16_floatFromInt_u32 { + try testing.expect(f16_floatFromInt_u32(0) == 0.0); + try testing.expect(f16_floatFromInt_u32(1) == 1.0); + try testing.expect(f16_floatFromInt_u32(65504) == 65504); + try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16)); } -test "conversion to f32" { - try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0); - try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24)); - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even - try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact +test f80_floatFromInt_u32 { + try testing.expect(f80_floatFromInt_u32(0) == 0.0); + try testing.expect(f80_floatFromInt_u32(1) == 1.0); + try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24)); } -test "conversion to f80" { - const floatFromInt = @import("./float_from_int.zig").floatFromInt; +test f80_floatFromInt_u64 { + try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0); +} + +test f80_floatFromInt_i128 { + try testing.expect(f80_floatFromInt_i128(-12) == -12); +} - try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12); - try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0); - try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); +test f80_floatFromInt_u128 { + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); - try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0); - try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24)); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64)); - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64)); + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up - try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up + try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact } diff --git a/lib/compiler_rt/floatdidf.zig b/lib/compiler_rt/floatdidf.zig deleted file mode 100644 index f8d5153d5b43896b3dd26a32e84f613151b84653..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdidf.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_l2d, "__aeabi_l2d"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatdidf, "__i64tod"); - } - symbol(&__floatdidf, "__floatdidf"); - } -} - -pub fn __floatdidf(a: i64) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatdihf.zig b/lib/compiler_rt/floatdihf.zig deleted file mode 100644 index c6865dff6b8025e49b8f1a0ffc36674c230247a4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdihf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatdihf, "__floatdihf"); -} - -fn __floatdihf(a: i64) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatdisf.zig b/lib/compiler_rt/floatdisf.zig deleted file mode 100644 index 3da1faba367a6a17b81f97c93db6ff2041765b84..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdisf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_l2f, "__aeabi_l2f"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatdisf, "__i64tos"); - } - symbol(&__floatdisf, "__floatdisf"); - } -} - -pub fn __floatdisf(a: i64) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatditf.zig b/lib/compiler_rt/floatditf.zig deleted file mode 100644 index 033c35ffcbdd2137d84890c9176d7c77fe29541e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatditf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatditf, "__floatdikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_xtoq, "_Qp_xtoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatditf, "_Q_lltoq"); - } - symbol(&__floatditf, "__floatditf"); -} - -pub fn __floatditf(a: i64) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatdixf.zig b/lib/compiler_rt/floatdixf.zig deleted file mode 100644 index 6bd06245d584402e7ed93b0d57d71f471bde05d4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatdixf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatdixf, "__floatdixf"); -} - -fn __floatdixf(a: i64) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floateidf.zig b/lib/compiler_rt/floateidf.zig deleted file mode 100644 index ac3972c28778600d342d0412741e9a3e41797546..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateidf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floateidf, "__floateidf"); -} - -pub fn __floateidf(a: [*]const u8, bits: usize) callconv(.c) f64 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateihf.zig b/lib/compiler_rt/floateihf.zig deleted file mode 100644 index c1ec290fb1084a05b6353ffde4968bce3c3cd3d8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateihf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateihf, "__floateihf"); -} - -pub fn __floateihf(a: [*]const u8, bits: usize) callconv(.c) f16 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateisf.zig b/lib/compiler_rt/floateisf.zig deleted file mode 100644 index dd5933b7dff321ee90d0b13ee6d9a5e0d85a9f20..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateisf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateisf, "__floateisf"); -} - -pub fn __floateisf(a: [*]const u8, bits: usize) callconv(.c) f32 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateitf.zig b/lib/compiler_rt/floateitf.zig deleted file mode 100644 index 0df893bd18881c9ec382e718a7664bf4d0f7a8e4..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateitf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateitf, "__floateitf"); -} - -pub fn __floateitf(a: [*]const u8, bits: usize) callconv(.c) f128 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floateixf.zig b/lib/compiler_rt/floateixf.zig deleted file mode 100644 index dafefa4e8f11b978f26b5e4d10cc8b0feeed480b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floateixf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floateixf, "__floateixf"); -} - -pub fn __floateixf(a: [*]const u8, bits: usize) callconv(.c) f80 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatsidf.zig b/lib/compiler_rt/floatsidf.zig deleted file mode 100644 index dc5a261a08f1e86155d7af20b62b43b02c99bbe5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsidf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_i2d, "__aeabi_i2d"); - } else { - symbol(&__floatsidf, "__floatsidf"); - } -} - -pub fn __floatsidf(a: i32) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatsihf.zig b/lib/compiler_rt/floatsihf.zig deleted file mode 100644 index e1d588cfb0da1ed1007496f3d32db0fcdd8612ef..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatsihf, "__floatsihf"); -} - -fn __floatsihf(a: i32) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatsisf.zig b/lib/compiler_rt/floatsisf.zig deleted file mode 100644 index 0dac860ebfded913a3eacb1666cb34e246f87dde..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsisf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_i2f, "__aeabi_i2f"); - } else { - symbol(&__floatsisf, "__floatsisf"); - } -} - -pub fn __floatsisf(a: i32) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatsitf.zig b/lib/compiler_rt/floatsitf.zig deleted file mode 100644 index 865ebce60fddaa5d8234cf76293b08e12be30000..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsitf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatsitf, "__floatsikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_itoq, "_Qp_itoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatsitf, "_Q_itoq"); - } - symbol(&__floatsitf, "__floatsitf"); -} - -pub fn __floatsitf(a: i32) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatsixf.zig b/lib/compiler_rt/floatsixf.zig deleted file mode 100644 index bd28eaf1fa68f9580f63b918bfeea6cc78295699..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatsixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floatsixf, "__floatsixf"); -} - -fn __floatsixf(a: i32) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floattidf.zig b/lib/compiler_rt/floattidf.zig deleted file mode 100644 index 02298705324edcd49b36f69a64c0c78873ecb57b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattidf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattidf, "__floattidf"); -} - -pub fn __floattidf(a: i128) callconv(.c) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floattihf.zig b/lib/compiler_rt/floattihf.zig deleted file mode 100644 index a751e3142c5b273819199105a6848c0280aee3c5..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattihf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattihf, "__floattihf"); -} - -pub fn __floattihf(a: i128) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floattisf.zig b/lib/compiler_rt/floattisf.zig deleted file mode 100644 index 72af61c6b6805d9bd03e6d215dd300fe7589c21f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattisf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floattisf, "__floattisf"); -} - -pub fn __floattisf(a: i128) callconv(.c) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floattitf.zig b/lib/compiler_rt/floattitf.zig deleted file mode 100644 index 3e49a68fd56912ebe7573346b6b8aea6b98b91ba..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattitf.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__floattitf, "__floattikf"); - symbol(&__floattitf, "__floattitf"); -} - -pub fn __floattitf(a: i128) callconv(.c) f128 { - return floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floattixf.zig b/lib/compiler_rt/floattixf.zig deleted file mode 100644 index be05180795aef517800c15d01c928bab4f7f19a0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floattixf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floattixf, "__floattixf"); -} - -pub fn __floattixf(a: i128) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatundidf.zig b/lib/compiler_rt/floatundidf.zig deleted file mode 100644 index 852675370503bab154245fd685ff2c2a5449aea0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundidf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ul2d, "__aeabi_ul2d"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatundidf, "__u64tod"); - } - symbol(&__floatundidf, "__floatundidf"); - } -} - -pub fn __floatundidf(a: u64) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatundihf.zig b/lib/compiler_rt/floatundihf.zig deleted file mode 100644 index 064d565d2dc4ec4f118dee8400375de802400f2b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatundihf, "__floatundihf"); -} - -fn __floatundihf(a: u64) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatundisf.zig b/lib/compiler_rt/floatundisf.zig deleted file mode 100644 index 827a419fd5315624866af773ea71a9098b2bcb3e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundisf.zig +++ /dev/null @@ -1,23 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ul2f, "__aeabi_ul2f"); - } else { - if (compiler_rt.want_windows_arm_abi) { - symbol(&__floatundisf, "__u64tos"); - } - symbol(&__floatundisf, "__floatundisf"); - } -} - -pub fn __floatundisf(a: u64) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatunditf.zig b/lib/compiler_rt/floatunditf.zig deleted file mode 100644 index 79f9f54e176f5741bbc901b1790895feaadf1f98..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunditf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatunditf, "__floatundikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_uxtoq, "_Qp_uxtoq"); - } else if (compiler_rt.want_sparc32_abi) { - @export(&__floatunditf, "_Q_ulltoq"); - } - symbol(&__floatunditf, "__floatunditf"); -} - -pub fn __floatunditf(a: u64) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatundixf.zig b/lib/compiler_rt/floatundixf.zig deleted file mode 100644 index ce36d47a4ef225c67e4e45f3695cdb14649cee4c..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatundixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatundixf, "__floatundixf"); -} - -fn __floatundixf(a: u64) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatuneidf.zig b/lib/compiler_rt/floatuneidf.zig deleted file mode 100644 index 6e391b7cf1c4baeacb55c731ca24c66750c6d346..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneidf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneidf, "__floatuneidf"); -} - -pub fn __floatuneidf(a: [*]const u8, bits: usize) callconv(.c) f64 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneihf.zig b/lib/compiler_rt/floatuneihf.zig deleted file mode 100644 index 0df0cf155be8e7d39afb5012940fa85ec3211603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneihf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneihf, "__floatuneihf"); -} - -pub fn __floatuneihf(a: [*]const u8, bits: usize) callconv(.c) f16 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneisf.zig b/lib/compiler_rt/floatuneisf.zig deleted file mode 100644 index e2dadd9ffddc6efe13ffd53bb9f2cdeeffc3530d..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneisf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneisf, "__floatuneisf"); -} - -pub fn __floatuneisf(a: [*]const u8, bits: usize) callconv(.c) f32 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneitf.zig b/lib/compiler_rt/floatuneitf.zig deleted file mode 100644 index ddee65dfb18b793bffe08d850384842fcff5747e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneitf.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("builtin"); - -const std = @import("std"); - -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneitf, "__floatuneitf"); -} - -pub fn __floatuneitf(a: [*]const u8, bits: usize) callconv(.c) f128 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatuneixf.zig b/lib/compiler_rt/floatuneixf.zig deleted file mode 100644 index 75dd565daffe16ffb4e95230266fca2f5d288603..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuneixf.zig +++ /dev/null @@ -1,14 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; - -comptime { - symbol(&__floatuneixf, "__floatuneixf"); -} - -pub fn __floatuneixf(a: [*]const u8, bits: usize) callconv(.c) f80 { - const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); - return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a[0..byte_size]))); -} diff --git a/lib/compiler_rt/floatunsidf.zig b/lib/compiler_rt/floatunsidf.zig deleted file mode 100644 index 94949c7bff4eafff900a0b22e53998a930c3d7ea..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsidf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ui2d, "__aeabi_ui2d"); - } else { - symbol(&__floatunsidf, "__floatunsidf"); - } -} - -pub fn __floatunsidf(a: u32) callconv(.c) f64 { - return floatFromInt(f64, a); -} - -fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatunsihf.zig b/lib/compiler_rt/floatunsihf.zig deleted file mode 100644 index a2e42ca10f3af950e900f5250fa6a3d23e2b1266..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsihf.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatunsihf, "__floatunsihf"); -} - -pub fn __floatunsihf(a: u32) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatunsisf.zig b/lib/compiler_rt/floatunsisf.zig deleted file mode 100644 index 04da1aa5c03cf76815cccf2273731501d1c8edc0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsisf.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_ui2f, "__aeabi_ui2f"); - } else { - symbol(&__floatunsisf, "__floatunsisf"); - } -} - -pub fn __floatunsisf(a: u32) callconv(.c) f32 { - return floatFromInt(f32, a); -} - -fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatunsitf.zig b/lib/compiler_rt/floatunsitf.zig deleted file mode 100644 index 2b7c58eab8bd7c2a238062e0cc123f5ce6b8c9e0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsitf.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__floatunsitf, "__floatunsikf"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_uitoq, "_Qp_uitoq"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__floatunsitf, "_Q_utoq"); - } - symbol(&__floatunsitf, "__floatunsitf"); -} - -pub fn __floatunsitf(a: u32) callconv(.c) f128 { - return floatFromInt(f128, a); -} - -fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void { - c.* = floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatunsixf.zig b/lib/compiler_rt/floatunsixf.zig deleted file mode 100644 index 906f0270f5c53d28970a0c250b24abcadfa72946..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatunsixf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatunsixf, "__floatunsixf"); -} - -fn __floatunsixf(a: u32) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floatuntidf.zig b/lib/compiler_rt/floatuntidf.zig deleted file mode 100644 index b770457bc4992a5bd6237d832e2ca4c0cbed11e0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntidf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__floatuntidf, "__floatuntidf"); -} - -pub fn __floatuntidf(a: u128) callconv(.c) f64 { - return floatFromInt(f64, a); -} diff --git a/lib/compiler_rt/floatuntihf.zig b/lib/compiler_rt/floatuntihf.zig deleted file mode 100644 index 5b4373cb7c496b0acf1a2fe6ef988872b30e8780..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntihf.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntihf, "__floatuntihf"); -} - -pub fn __floatuntihf(a: u128) callconv(.c) f16 { - return floatFromInt(f16, a); -} diff --git a/lib/compiler_rt/floatuntisf.zig b/lib/compiler_rt/floatuntisf.zig deleted file mode 100644 index de9a021476edecfcc26761133c0645d799c677da..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntisf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntisf, "__floatuntisf"); -} - -pub fn __floatuntisf(a: u128) callconv(.c) f32 { - return floatFromInt(f32, a); -} diff --git a/lib/compiler_rt/floatuntitf.zig b/lib/compiler_rt/floatuntitf.zig deleted file mode 100644 index 47cd65cc3ff4460d937e0ccd7acabb2455ae704a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntitf.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const floatFromInt = @import("./float_from_int.zig").floatFromInt; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) - symbol(&__floatuntitf, "__floatuntikf"); - symbol(&__floatuntitf, "__floatuntitf"); -} - -pub fn __floatuntitf(a: u128) callconv(.c) f128 { - return floatFromInt(f128, a); -} diff --git a/lib/compiler_rt/floatuntixf.zig b/lib/compiler_rt/floatuntixf.zig deleted file mode 100644 index 41fb45b3a3a1b8e213c03a4ef5e847feb8d31211..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/floatuntixf.zig +++ /dev/null @@ -1,12 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const floatFromInt = @import("./float_from_int.zig").floatFromInt; - -comptime { - symbol(&__floatuntixf, "__floatuntixf"); -} - -pub fn __floatuntixf(a: u128) callconv(.c) f80 { - return floatFromInt(f80, a); -} diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig index f81d2e0011286a1ea45a3ef147fc704eadac4b4e..f31c352d026c549bd230c9d7d5f15677a85968ce 100644 --- a/lib/compiler_rt/floor_ceil.zig +++ b/lib/compiler_rt/floor_ceil.zig @@ -15,7 +15,7 @@ const mem = std.mem; const expect = std.testing.expect; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { // floor @@ -41,52 +41,92 @@ comptime { symbol(&ceill, "ceill"); } -pub fn __floorh(x: f16) callconv(.c) f16 { +fn __floorh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(floor_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn floor_f16(x: f16) f16 { return impl(f16, .floor, x); } -pub fn floorf(x: f32) callconv(.c) f32 { +fn floorf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(floor_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn floor_f32(x: f32) f32 { return impl(f32, .floor, x); } -pub fn floor(x: f64) callconv(.c) f64 { +fn floor(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(floor_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn floor_f64(x: f64) f64 { return impl(f64, .floor, x); } -pub fn __floorx(x: f80) callconv(.c) f80 { +fn __floorx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(floor_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn floor_f80(x: f80) f80 { return impl(f80, .floor, x); } -pub fn floorq(x: f128) callconv(.c) f128 { +fn floorq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(floor_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn floor_f128(x: f128) f128 { return impl(f128, .floor, x); } pub fn floorl(x: c_longdouble) callconv(.c) c_longdouble { - return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .floor, x); + switch (@typeInfo(c_longdouble).float.bits) { + 64 => return floor_f64(x), + 80 => return floor_f80(x), + 128 => return floor_f128(x), + else => comptime unreachable, + } } -pub fn __ceilh(x: f16) callconv(.c) f16 { +fn __ceilh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(ceil_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn ceil_f16(x: f16) f16 { return impl(f16, .ceil, x); } -pub fn ceilf(x: f32) callconv(.c) f32 { +fn ceilf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(ceil_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn ceil_f32(x: f32) f32 { return impl(f32, .ceil, x); } -pub fn ceil(x: f64) callconv(.c) f64 { +fn ceil(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(ceil_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn ceil_f64(x: f64) f64 { return impl(f64, .ceil, x); } -pub fn __ceilx(x: f80) callconv(.c) f80 { +fn __ceilx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(ceil_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn ceil_f80(x: f80) f80 { return impl(f80, .ceil, x); } -pub fn ceilq(x: f128) callconv(.c) f128 { +fn ceilq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(ceil_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn ceil_f128(x: f128) f128 { return impl(f128, .ceil, x); } pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble { - return impl(std.meta.Float(@bitSizeOf(c_longdouble)), .ceil, x); + switch (@typeInfo(c_longdouble).float.bits) { + 64 => return ceil_f64(x), + 80 => return ceil_f80(x), + 128 => return ceil_f128(x), + else => comptime unreachable, + } } inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { @@ -144,142 +184,122 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { } } -test "floor16" { - try expect(__floorh(1.3) == 1.0); - try expect(__floorh(-1.3) == -2.0); - try expect(__floorh(0.2) == 0.0); -} - -test "floor32" { - try expect(floorf(1.3) == 1.0); - try expect(floorf(-1.3) == -2.0); - try expect(floorf(0.2) == 0.0); -} - -test "floor64" { - try expect(floor(1.3) == 1.0); - try expect(floor(-1.3) == -2.0); - try expect(floor(0.2) == 0.0); -} - -test "floor80" { - try expect(__floorx(1.3) == 1.0); - try expect(__floorx(-1.3) == -2.0); - try expect(__floorx(0.2) == 0.0); -} - -test "floor128" { - try expect(floorq(1.3) == 1.0); - try expect(floorq(-1.3) == -2.0); - try expect(floorq(0.2) == 0.0); -} - -test "floor16.special" { - try expect(__floorh(0.0) == 0.0); - try expect(__floorh(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorh(math.inf(f16)))); - try expect(math.isNegativeInf(__floorh(-math.inf(f16)))); - try expect(math.isNan(__floorh(math.nan(f16)))); -} - -test "floor32.special" { - try expect(floorf(0.0) == 0.0); - try expect(floorf(-0.0) == -0.0); - try expect(math.isPositiveInf(floorf(math.inf(f32)))); - try expect(math.isNegativeInf(floorf(-math.inf(f32)))); - try expect(math.isNan(floorf(math.nan(f32)))); -} - -test "floor64.special" { - try expect(floor(0.0) == 0.0); - try expect(floor(-0.0) == -0.0); - try expect(math.isPositiveInf(floor(math.inf(f64)))); - try expect(math.isNegativeInf(floor(-math.inf(f64)))); - try expect(math.isNan(floor(math.nan(f64)))); -} - -test "floor80.special" { - try expect(__floorx(0.0) == 0.0); - try expect(__floorx(-0.0) == -0.0); - try expect(math.isPositiveInf(__floorx(math.inf(f80)))); - try expect(math.isNegativeInf(__floorx(-math.inf(f80)))); - try expect(math.isNan(__floorx(math.nan(f80)))); -} - -test "floor128.special" { - try expect(floorq(0.0) == 0.0); - try expect(floorq(-0.0) == -0.0); - try expect(math.isPositiveInf(floorq(math.inf(f128)))); - try expect(math.isNegativeInf(floorq(-math.inf(f128)))); - try expect(math.isNan(floorq(math.nan(f128)))); -} - -test "ceil16" { - try expect(__ceilh(1.3) == 2.0); - try expect(__ceilh(-1.3) == -1.0); - try expect(__ceilh(0.2) == 1.0); -} - -test "ceil32" { - try expect(ceilf(1.3) == 2.0); - try expect(ceilf(-1.3) == -1.0); - try expect(ceilf(0.2) == 1.0); -} - -test "ceil64" { - try expect(ceil(1.3) == 2.0); - try expect(ceil(-1.3) == -1.0); - try expect(ceil(0.2) == 1.0); -} - -test "ceil80" { - try expect(__ceilx(1.3) == 2.0); - try expect(__ceilx(-1.3) == -1.0); - try expect(__ceilx(0.2) == 1.0); -} - -test "ceil128" { - try expect(ceilq(1.3) == 2.0); - try expect(ceilq(-1.3) == -1.0); - try expect(ceilq(0.2) == 1.0); -} - -test "ceil16.special" { - try expect(__ceilh(0.0) == 0.0); - try expect(__ceilh(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilh(math.inf(f16)))); - try expect(math.isNegativeInf(__ceilh(-math.inf(f16)))); - try expect(math.isNan(__ceilh(math.nan(f16)))); -} - -test "ceil32.special" { - try expect(ceilf(0.0) == 0.0); - try expect(ceilf(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilf(math.inf(f32)))); - try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); - try expect(math.isNan(ceilf(math.nan(f32)))); -} - -test "ceil64.special" { - try expect(ceil(0.0) == 0.0); - try expect(ceil(-0.0) == -0.0); - try expect(math.isPositiveInf(ceil(math.inf(f64)))); - try expect(math.isNegativeInf(ceil(-math.inf(f64)))); - try expect(math.isNan(ceil(math.nan(f64)))); -} - -test "ceil80.special" { - try expect(__ceilx(0.0) == 0.0); - try expect(__ceilx(-0.0) == -0.0); - try expect(math.isPositiveInf(__ceilx(math.inf(f80)))); - try expect(math.isNegativeInf(__ceilx(-math.inf(f80)))); - try expect(math.isNan(__ceilx(math.nan(f80)))); -} - -test "ceil128.special" { - try expect(ceilq(0.0) == 0.0); - try expect(ceilq(-0.0) == -0.0); - try expect(math.isPositiveInf(ceilq(math.inf(f128)))); - try expect(math.isNegativeInf(ceilq(-math.inf(f128)))); - try expect(math.isNan(ceilq(math.nan(f128)))); +test floor_f16 { + try expect(floor_f16(1.3) == 1.0); + try expect(floor_f16(-1.3) == -2.0); + try expect(floor_f16(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f16(0.2))); + try expect(math.isPositiveZero(floor_f16(0.0))); + try expect(math.isNegativeZero(floor_f16(-0.0))); + try expect(math.isPositiveInf(floor_f16(math.inf(f16)))); + try expect(math.isNegativeInf(floor_f16(-math.inf(f16)))); + try expect(math.isNan(floor_f16(math.nan(f16)))); +} + +test floor_f32 { + try expect(floor_f32(1.3) == 1.0); + try expect(floor_f32(-1.3) == -2.0); + try expect(floor_f32(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f32(0.2))); + try expect(math.isPositiveZero(floor_f32(0.0))); + try expect(math.isNegativeZero(floor_f32(-0.0))); + try expect(math.isPositiveInf(floor_f32(math.inf(f32)))); + try expect(math.isNegativeInf(floor_f32(-math.inf(f32)))); + try expect(math.isNan(floor_f32(math.nan(f32)))); +} + +test floor_f64 { + try expect(floor_f64(1.3) == 1.0); + try expect(floor_f64(-1.3) == -2.0); + try expect(floor_f64(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f64(0.2))); + try expect(math.isPositiveZero(floor_f64(0.0))); + try expect(math.isNegativeZero(floor_f64(-0.0))); + try expect(math.isPositiveInf(floor_f64(math.inf(f64)))); + try expect(math.isNegativeInf(floor_f64(-math.inf(f64)))); + try expect(math.isNan(floor_f64(math.nan(f64)))); +} + +test floor_f80 { + try expect(floor_f80(1.3) == 1.0); + try expect(floor_f80(-1.3) == -2.0); + try expect(floor_f80(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f80(0.2))); + try expect(math.isPositiveZero(floor_f80(0.0))); + try expect(math.isNegativeZero(floor_f80(-0.0))); + try expect(math.isPositiveInf(floor_f80(math.inf(f80)))); + try expect(math.isNegativeInf(floor_f80(-math.inf(f80)))); + try expect(math.isNan(floor_f80(math.nan(f80)))); +} + +test floor_f128 { + try expect(floor_f128(1.3) == 1.0); + try expect(floor_f128(-1.3) == -2.0); + try expect(floor_f128(-0.2) == -1.0); + try expect(math.isPositiveZero(floor_f128(0.2))); + try expect(math.isPositiveZero(floor_f128(0.0))); + try expect(math.isNegativeZero(floor_f128(-0.0))); + try expect(math.isPositiveInf(floor_f128(math.inf(f128)))); + try expect(math.isNegativeInf(floor_f128(-math.inf(f128)))); + try expect(math.isNan(floor_f128(math.nan(f128)))); +} + +test ceil_f16 { + try expect(ceil_f16(1.3) == 2.0); + try expect(ceil_f16(-1.3) == -1.0); + try expect(ceil_f16(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f16(-0.2))); + try expect(math.isPositiveZero(ceil_f16(0.0))); + try expect(math.isNegativeZero(ceil_f16(-0.0))); + try expect(math.isPositiveInf(ceil_f16(math.inf(f16)))); + try expect(math.isNegativeInf(ceil_f16(-math.inf(f16)))); + try expect(math.isNan(ceil_f16(math.nan(f16)))); +} + +test ceil_f32 { + try expect(ceil_f32(1.3) == 2.0); + try expect(ceil_f32(-1.3) == -1.0); + try expect(ceil_f32(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f32(-0.2))); + try expect(math.isPositiveZero(ceil_f32(0.0))); + try expect(math.isNegativeZero(ceil_f32(-0.0))); + try expect(math.isPositiveInf(ceil_f32(math.inf(f32)))); + try expect(math.isNegativeInf(ceil_f32(-math.inf(f32)))); + try expect(math.isNan(ceil_f32(math.nan(f32)))); +} + +test ceil_f64 { + try expect(ceil_f64(1.3) == 2.0); + try expect(ceil_f64(-1.3) == -1.0); + try expect(ceil_f64(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f64(-0.2))); + try expect(math.isPositiveZero(ceil_f64(0.0))); + try expect(math.isNegativeZero(ceil_f64(-0.0))); + try expect(math.isPositiveInf(ceil_f64(math.inf(f64)))); + try expect(math.isNegativeInf(ceil_f64(-math.inf(f64)))); + try expect(math.isNan(ceil_f64(math.nan(f64)))); +} + +test ceil_f80 { + try expect(ceil_f80(1.3) == 2.0); + try expect(ceil_f80(-1.3) == -1.0); + try expect(ceil_f80(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f80(-0.2))); + try expect(math.isPositiveZero(ceil_f80(0.0))); + try expect(math.isNegativeZero(ceil_f80(-0.0))); + try expect(math.isPositiveInf(ceil_f80(math.inf(f80)))); + try expect(math.isNegativeInf(ceil_f80(-math.inf(f80)))); + try expect(math.isNan(ceil_f80(math.nan(f80)))); +} + +test ceil_f128 { + try expect(ceil_f128(1.3) == 2.0); + try expect(ceil_f128(-1.3) == -1.0); + try expect(ceil_f128(0.2) == 1.0); + try expect(math.isNegativeZero(ceil_f128(-0.2))); + try expect(math.isPositiveZero(ceil_f128(0.0))); + try expect(math.isNegativeZero(ceil_f128(-0.0))); + try expect(math.isPositiveInf(ceil_f128(math.inf(f128)))); + try expect(math.isNegativeInf(ceil_f128(-math.inf(f128)))); + try expect(math.isNan(ceil_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index 61732585db2ece3fb84c3029293cab41662781d2..f10d08fc63f2038fa98cd4b28c5d4ee8a2ca0a84 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -23,12 +23,18 @@ comptime { symbol(&fmal, "fmal"); } -pub fn __fmah(x: f16, y: f16, z: f16) callconv(.c) f16 { +fn __fmah(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi, z: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fma_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y), compiler_rt.f16.fromAbi(z))); +} +pub fn fma_f16(x: f16, y: f16, z: f16) f16 { // TODO: more efficient implementation - return @floatCast(fmaf(x, y, z)); + return @floatCast(fma_f32(x, y, z)); } -pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 { +fn fmaf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi, z: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fma_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y), compiler_rt.f32.fromAbi(z))); +} +pub fn fma_f32(x: f32, y: f32, z: f32) f32 { const xy = @as(f64, x) * y; const xy_z = xy + z; const u = @as(u64, @bitCast(xy_z)); @@ -42,8 +48,11 @@ pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 { } } +fn fma(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi, z: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fma_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y), compiler_rt.f64.fromAbi(z))); +} /// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately. -pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { +pub fn fma_f64(x: f64, y: f64, z: f64) f64 { if (!math.isFinite(x) or !math.isFinite(y)) { return x * y + z; } @@ -90,11 +99,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { } } -pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 { +fn __fmax(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi, c: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fma_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b), compiler_rt.f80.fromAbi(c))); +} +pub fn fma_f80(a: f80, b: f80, c: f80) f80 { // TODO: more efficient implementation - return @floatCast(fmaq(a, b, c)); + return @floatCast(fma_f128(a, b, c)); } +fn fmaq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi, z: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fma_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y), compiler_rt.f128.fromAbi(z))); +} /// Fused multiply-add: Compute x * y + z with a single rounding error. /// /// We use scaling to avoid overflow/underflow, along with the @@ -102,7 +117,7 @@ pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 { /// /// Dekker, T. A Floating-Point Technique for Extending the /// Available Precision. Numer. Math. 18, 224-242 (1971). -pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { +pub fn fma_f128(x: f128, y: f128, z: f128) f128 { if (!math.isFinite(x) or !math.isFinite(y)) { return x * y + z; } @@ -151,10 +166,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fma(x, y, z), - 80 => return __fmax(x, y, z), - 128 => return fmaq(x, y, z), - else => @compileError("unreachable"), + 64 => return fma_f64(x, y, z), + 80 => return fma_f80(x, y, z), + 128 => return fma_f128(x, y, z), + else => comptime unreachable, } } @@ -316,35 +331,35 @@ fn dd_mul128(a: f128, b: f128) dd128 { test "32" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(37.45, 5.0, 9.124), 196.374004, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(89.123, 5.0, 9.124), 454.739005, epsilon)); - try expect(math.approxEqAbs(f32, fmaf(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(37.45, 5.0, 9.124), 196.374004, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(89.123, 5.0, 9.124), 454.739005, epsilon)); + try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } test "64" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f64, fma(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f64, fma(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f64, fma(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f64, fma(37.45, 5.0, 9.124), 196.374, epsilon)); - try expect(math.approxEqAbs(f64, fma(89.123, 5.0, 9.124), 454.739, epsilon)); - try expect(math.approxEqAbs(f64, fma(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(37.45, 5.0, 9.124), 196.374, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(89.123, 5.0, 9.124), 454.739, epsilon)); + try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } test "128" { const epsilon = 0.000001; - try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(0.2, 5.0, 9.124), 10.124, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(0.8923, 5.0, 9.124), 13.5855, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(1.5, 5.0, 9.124), 16.624, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(37.45, 5.0, 9.124), 196.374, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(89.123, 5.0, 9.124), 454.739, epsilon)); - try expect(math.approxEqAbs(f128, fmaq(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.0, 5.0, 9.124), 9.124, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.2, 5.0, 9.124), 10.124, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(0.8923, 5.0, 9.124), 13.5855, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(1.5, 5.0, 9.124), 16.624, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(37.45, 5.0, 9.124), 196.374, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(89.123, 5.0, 9.124), 454.739, epsilon)); + try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); } diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index 317d93f2d3e42fcfb88c4f36fe2203dab6bfeed2..cf323533952e542e126e11f69ec5a8352c37bcdb 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -17,32 +17,47 @@ comptime { symbol(&fmaxl, "fmaxl"); } -pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 { +fn __fmaxh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmax_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y))); +} +pub fn fmax_f16(x: f16, y: f16) f16 { return generic_fmax(f16, x, y); } -pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 { +fn fmaxf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmax_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y))); +} +pub fn fmax_f32(x: f32, y: f32) f32 { return generic_fmax(f32, x, y); } -pub fn fmax(x: f64, y: f64) callconv(.c) f64 { +fn fmax(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmax_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y))); +} +pub fn fmax_f64(x: f64, y: f64) f64 { return generic_fmax(f64, x, y); } -pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 { +fn __fmaxx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmax_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y))); +} +pub fn fmax_f80(x: f80, y: f80) f80 { return generic_fmax(f80, x, y); } -pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 { +fn fmaxq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmax_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y))); +} +pub fn fmax_f128(x: f128, y: f128) f128 { return generic_fmax(f128, x, y); } pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmax(x, y), - 80 => return __fmaxx(x, y), - 128 => return fmaxq(x, y), - else => @compileError("unreachable"), + 64 => return fmax_f64(x, y), + 80 => return fmax_f80(x, y), + 128 => return fmax_f128(x, y), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index 36cf9c121bbf17c1e282cfcf982f69ce7f1ec17c..48b5dcdc225118ce3a2096b15c98b0b534f75ae3 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -17,32 +17,47 @@ comptime { symbol(&fminl, "fminl"); } -pub fn __fminh(x: f16, y: f16) callconv(.c) f16 { +fn __fminh(x: compiler_rt.f16.Abi, y: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmin_f16(compiler_rt.f16.fromAbi(x), compiler_rt.f16.fromAbi(y))); +} +pub fn fmin_f16(x: f16, y: f16) f16 { return generic_fmin(f16, x, y); } -pub fn fminf(x: f32, y: f32) callconv(.c) f32 { +fn fminf(x: compiler_rt.f32.Abi, y: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmin_f32(compiler_rt.f32.fromAbi(x), compiler_rt.f32.fromAbi(y))); +} +pub fn fmin_f32(x: f32, y: f32) f32 { return generic_fmin(f32, x, y); } -pub fn fmin(x: f64, y: f64) callconv(.c) f64 { +fn fmin(x: compiler_rt.f64.Abi, y: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmin_f64(compiler_rt.f64.fromAbi(x), compiler_rt.f64.fromAbi(y))); +} +pub fn fmin_f64(x: f64, y: f64) f64 { return generic_fmin(f64, x, y); } -pub fn __fminx(x: f80, y: f80) callconv(.c) f80 { +fn __fminx(x: compiler_rt.f80.Abi, y: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmin_f80(compiler_rt.f80.fromAbi(x), compiler_rt.f80.fromAbi(y))); +} +pub fn fmin_f80(x: f80, y: f80) f80 { return generic_fmin(f80, x, y); } -pub fn fminq(x: f128, y: f128) callconv(.c) f128 { +fn fminq(x: compiler_rt.f128.Abi, y: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmin_f128(compiler_rt.f128.fromAbi(x), compiler_rt.f128.fromAbi(y))); +} +pub fn fmin_f128(x: f128, y: f128) f128 { return generic_fmin(f128, x, y); } pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmin(x, y), - 80 => return __fminx(x, y), - 128 => return fminq(x, y), - else => @compileError("unreachable"), + 64 => return fmin_f64(x, y), + 80 => return fmin_f80(x, y), + 128 => return fmin_f128(x, y), + else => comptime unreachable, } } diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 009eedd8ac84ab7eb905a74900fc17d07e8be421..636138516bf1f13d2a15b597d21fd6a617e7ee0d 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -19,22 +19,34 @@ comptime { symbol(&fmodl, "fmodl"); } -pub fn __fmodh(x: f16, y: f16) callconv(.c) f16 { +fn __fmodh(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(fmod_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn fmod_f16(x: f16, y: f16) f16 { // TODO: more efficient implementation - return @floatCast(fmodf(x, y)); + return @floatCast(fmod_f32(x, y)); } -pub fn fmodf(x: f32, y: f32) callconv(.c) f32 { +fn fmodf(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(fmod_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +pub fn fmod_f32(x: f32, y: f32) f32 { return generic_fmod(f32, x, y); } -pub fn fmod(x: f64, y: f64) callconv(.c) f64 { +fn fmod(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(fmod_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +pub fn fmod_f64(x: f64, y: f64) f64 { return generic_fmod(f64, x, y); } +fn __fmodx(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(fmod_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} /// fmodx - floating modulo large, returns the remainder of division for f80 types /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits -pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { +pub fn fmod_f80(a: f80, b: f80) f80 { const T = f80; const Z = @Int(.unsigned, @bitSizeOf(T)); @@ -130,9 +142,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { } } +fn fmodq(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(fmod_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} /// fmodq - floating modulo large, returns the remainder of division for f128 types /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits -pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { +pub fn fmod_f128(a: f128, b: f128) f128 { var amod = a; var bmod = b; const aPtr_u64: [*]u64 = @ptrCast(&amod); @@ -251,10 +266,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return fmod(a, b), - 80 => return __fmodx(a, b), - 128 => return fmodq(a, b), - else => @compileError("unreachable"), + 64 => return fmod_f64(a, b), + 80 => return fmod_f80(a, b), + 128 => return fmod_f128(a, b), + else => comptime unreachable, } } @@ -342,42 +357,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T { return @bitCast(ux); } -test "fmodf" { +test fmod_f32 { const nan_val = math.nan(f32); const inf_val = math.inf(f32); - try std.testing.expect(math.isNan(fmodf(nan_val, 1.0))); - try std.testing.expect(math.isNan(fmodf(1.0, nan_val))); - try std.testing.expect(math.isNan(fmodf(inf_val, 1.0))); - try std.testing.expect(math.isNan(fmodf(0.0, 0.0))); - try std.testing.expect(math.isNan(fmodf(1.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val))); + try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f32(1.0, 0.0))); - try std.testing.expectEqual(@as(f32, 0.0), fmodf(0.0, 2.0)); - try std.testing.expectEqual(@as(f32, -0.0), fmodf(-0.0, 2.0)); + try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0)); + try std.testing.expectEqual(@as(f32, -0.0), fmod_f32(-0.0, 2.0)); - try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, 10.0)); - try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0)); - try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0)); - try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0)); + try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0)); + try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0)); + try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0)); + try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0)); } -test "fmod" { +test fmod_f64 { const nan_val = math.nan(f64); const inf_val = math.inf(f64); - try std.testing.expect(math.isNan(fmod(nan_val, 1.0))); - try std.testing.expect(math.isNan(fmod(1.0, nan_val))); - try std.testing.expect(math.isNan(fmod(inf_val, 1.0))); - try std.testing.expect(math.isNan(fmod(0.0, 0.0))); - try std.testing.expect(math.isNan(fmod(1.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val))); + try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0))); + try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0))); + try std.testing.expect(math.isNan(fmod_f64(1.0, 0.0))); - try std.testing.expectEqual(@as(f64, 0.0), fmod(0.0, 2.0)); - try std.testing.expectEqual(@as(f64, -0.0), fmod(-0.0, 2.0)); + try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0)); + try std.testing.expectEqual(@as(f64, -0.0), fmod_f64(-0.0, 2.0)); - try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, 10.0)); - try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0)); - try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0)); - try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0)); + try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0)); + try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0)); + try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0)); + try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0)); } test { diff --git a/lib/compiler_rt/fmodq_test.zig b/lib/compiler_rt/fmodq_test.zig index 07ddb8d182e41fe2ff80414aeff256728e1ce365..b98dc0762e664f09b0d648e290658bf4502da416 100644 --- a/lib/compiler_rt/fmodq_test.zig +++ b/lib/compiler_rt/fmodq_test.zig @@ -1,52 +1,52 @@ const std = @import("std"); -const fmod = @import("fmod.zig"); +const fmod_f128 = @import("fmod.zig").fmod_f128; const testing = std.testing; -fn test_fmodq(a: f128, b: f128, exp: f128) !void { - const res = fmod.fmodq(a, b); +fn test_fmod_f128(a: f128, b: f128, exp: f128) !void { + const res = fmod_f128(a, b); try testing.expect(exp == res); } -fn test_fmodq_nans() !void { - try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128)))); - try testing.expect(std.math.isNan(fmod.fmodq(1.0, -std.math.nan(f128)))); - try testing.expect(std.math.isNan(fmod.fmodq(std.math.nan(f128), 1.0))); - try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0))); +fn test_fmod_f128_nans() !void { + try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128)))); + try testing.expect(std.math.isNan(fmod_f128(1.0, -std.math.nan(f128)))); + try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0))); + try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0))); } -fn test_fmodq_infs() !void { - try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0); - try testing.expect(fmod.fmodq(1.0, -std.math.inf(f128)) == 1.0); - try testing.expect(std.math.isNan(fmod.fmodq(std.math.inf(f128), 1.0))); - try testing.expect(std.math.isNan(fmod.fmodq(-std.math.inf(f128), 1.0))); +fn test_fmod_f128_infs() !void { + try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0); + try testing.expect(fmod_f128(1.0, -std.math.inf(f128)) == 1.0); + try testing.expect(std.math.isNan(fmod_f128(std.math.inf(f128), 1.0))); + try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0))); } -test "fmodq" { - try test_fmodq(6.8, 4.0, 2.8); - try test_fmodq(6.8, -4.0, 2.8); - try test_fmodq(-6.8, 4.0, -2.8); - try test_fmodq(-6.8, -4.0, -2.8); - try test_fmodq(3.0, 2.0, 1.0); - try test_fmodq(-5.0, 3.0, -2.0); - try test_fmodq(3.0, 2.0, 1.0); - try test_fmodq(1.0, 2.0, 1.0); - try test_fmodq(0.0, 1.0, 0.0); - try test_fmodq(-0.0, 1.0, -0.0); - try test_fmodq(7046119.0, 5558362.0, 1487757.0); - try test_fmodq(9010357.0, 1957236.0, 1181413.0); - try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0); - try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); +test fmod_f128 { + try test_fmod_f128(6.8, 4.0, 2.8); + try test_fmod_f128(6.8, -4.0, 2.8); + try test_fmod_f128(-6.8, 4.0, -2.8); + try test_fmod_f128(-6.8, -4.0, -2.8); + try test_fmod_f128(3.0, 2.0, 1.0); + try test_fmod_f128(-5.0, 3.0, -2.0); + try test_fmod_f128(3.0, 2.0, 1.0); + try test_fmod_f128(1.0, 2.0, 1.0); + try test_fmod_f128(0.0, 1.0, 0.0); + try test_fmod_f128(-0.0, 1.0, -0.0); + try test_fmod_f128(7046119.0, 5558362.0, 1487757.0); + try test_fmod_f128(9010357.0, 1957236.0, 1181413.0); + try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0); + try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); // Denormals const a1: f128 = 0xedcb34a235253948765432134674p-16494; const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494; const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494; - try test_fmodq(a1, b1, exp1); + try test_fmod_f128(a1, b1, exp1); const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382; const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382; const exp2: f128 = 0x0.0001_aecd_9d66_4a6e_67b7_d7d0_a901p-16382; - try test_fmodq(a2, b2, exp2); + try test_fmod_f128(a2, b2, exp2); - try test_fmodq_nans(); - try test_fmodq_infs(); + try test_fmod_f128_nans(); + try test_fmod_f128_infs(); } diff --git a/lib/compiler_rt/fmodx_test.zig b/lib/compiler_rt/fmodx_test.zig index ca8229147ab693264b555676af664e7bf8acccbc..b32d354094ed97a1ab8d7c9d840610b9a8ac12a7 100644 --- a/lib/compiler_rt/fmodx_test.zig +++ b/lib/compiler_rt/fmodx_test.zig @@ -1,52 +1,52 @@ const std = @import("std"); const builtin = @import("builtin"); -const fmod = @import("fmod.zig"); +const fmod_f80 = @import("fmod.zig").fmod_f80; const testing = std.testing; -fn test_fmodx(a: f80, b: f80, exp: f80) !void { - const res = fmod.__fmodx(a, b); +fn test_fmod_f80(a: f80, b: f80, exp: f80) !void { + const res = fmod_f80(a, b); try testing.expect(exp == res); } -fn test_fmodx_nans() !void { - try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80)))); - try testing.expect(std.math.isNan(fmod.__fmodx(1.0, -std.math.nan(f80)))); - try testing.expect(std.math.isNan(fmod.__fmodx(std.math.nan(f80), 1.0))); - try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0))); +fn test_fmod_f80_nans() !void { + try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80)))); + try testing.expect(std.math.isNan(fmod_f80(1.0, -std.math.nan(f80)))); + try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0))); + try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0))); } -fn test_fmodx_infs() !void { - try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0); - try testing.expect(fmod.__fmodx(1.0, -std.math.inf(f80)) == 1.0); - try testing.expect(std.math.isNan(fmod.__fmodx(std.math.inf(f80), 1.0))); - try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.inf(f80), 1.0))); +fn test_fmod_f80_infs() !void { + try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0); + try testing.expect(fmod_f80(1.0, -std.math.inf(f80)) == 1.0); + try testing.expect(std.math.isNan(fmod_f80(std.math.inf(f80), 1.0))); + try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0))); } -test "fmodx" { - try test_fmodx(6.4, 4.0, 2.4); - try test_fmodx(6.4, -4.0, 2.4); - try test_fmodx(-6.4, 4.0, -2.4); - try test_fmodx(-6.4, -4.0, -2.4); - try test_fmodx(3.0, 2.0, 1.0); - try test_fmodx(-5.0, 3.0, -2.0); - try test_fmodx(3.0, 2.0, 1.0); - try test_fmodx(1.0, 2.0, 1.0); - try test_fmodx(0.0, 1.0, 0.0); - try test_fmodx(-0.0, 1.0, -0.0); - try test_fmodx(7046119.0, 5558362.0, 1487757.0); - try test_fmodx(9010357.0, 1957236.0, 1181413.0); - try test_fmodx(9223372036854775807, 10.0, 7.0); +test fmod_f80 { + try test_fmod_f80(6.4, 4.0, 2.4); + try test_fmod_f80(6.4, -4.0, 2.4); + try test_fmod_f80(-6.4, 4.0, -2.4); + try test_fmod_f80(-6.4, -4.0, -2.4); + try test_fmod_f80(3.0, 2.0, 1.0); + try test_fmod_f80(-5.0, 3.0, -2.0); + try test_fmod_f80(3.0, 2.0, 1.0); + try test_fmod_f80(1.0, 2.0, 1.0); + try test_fmod_f80(0.0, 1.0, 0.0); + try test_fmod_f80(-0.0, 1.0, -0.0); + try test_fmod_f80(7046119.0, 5558362.0, 1487757.0); + try test_fmod_f80(9010357.0, 1957236.0, 1181413.0); + try test_fmod_f80(9223372036854775807, 10.0, 7.0); // Denormals const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381; const exp1: f80 = 0x0.19b7_61d7_fd96_dc30p-16381; - try test_fmodx(a1, b1, exp1); + try test_fmod_f80(a1, b1, exp1); const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381; const exp2: f80 = 0x0.022c_b86c_a6a3_9ad4p-16381; - try test_fmodx(a2, b2, exp2); + try test_fmod_f80(a2, b2, exp2); - try test_fmodx_nans(); - try test_fmodx_infs(); + try test_fmod_f80_nans(); + try test_fmod_f80_infs(); } diff --git a/lib/compiler_rt/gedf2.zig b/lib/compiler_rt/gedf2.zig deleted file mode 100644 index f6b4b6d718fd20d8068244cfa6250f030f890e92..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gedf2.zig +++ /dev/null @@ -1,35 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpge, "__aeabi_dcmpge"); - symbol(&__aeabi_dcmpgt, "__aeabi_dcmpgt"); - } else { - symbol(&__gedf2, "__gedf2"); - symbol(&__gtdf2, "__gtdf2"); - } -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gedf2(a: f64, b: f64) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f64, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gtdf2(a: f64, b: f64) callconv(.c) i32 { - return __gedf2(a, b); -} - -fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) != .Less); -} - -fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) == .Greater); -} diff --git a/lib/compiler_rt/gehf2.zig b/lib/compiler_rt/gehf2.zig deleted file mode 100644 index 8008a06849887d2f317be4517a5cb6c485c2675a..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gehf2.zig +++ /dev/null @@ -1,21 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const symbol = @import("../compiler_rt.zig").symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__gehf2, "__gehf2"); - symbol(&__gthf2, "__gthf2"); -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gehf2(a: f16, b: f16) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f16, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gthf2(a: f16, b: f16) callconv(.c) i32 { - return __gehf2(a, b); -} diff --git a/lib/compiler_rt/gesf2.zig b/lib/compiler_rt/gesf2.zig deleted file mode 100644 index 7f5022104eba9378efe6184befcd7f40f479306f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gesf2.zig +++ /dev/null @@ -1,35 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fcmpge, "__aeabi_fcmpge"); - symbol(&__aeabi_fcmpgt, "__aeabi_fcmpgt"); - } else { - symbol(&__gesf2, "__gesf2"); - symbol(&__gtsf2, "__gtsf2"); - } -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -pub fn __gesf2(a: f32, b: f32) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f32, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -pub fn __gtsf2(a: f32, b: f32) callconv(.c) i32 { - return __gesf2(a, b); -} - -fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f32, comparef.GE, a, b) != .Less); -} - -fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(comparef.cmpf2(f32, comparef.LE, a, b) == .Greater); -} diff --git a/lib/compiler_rt/getf2.zig b/lib/compiler_rt/getf2.zig deleted file mode 100644 index 88a91600f1e32c5f7124f5e9be9d5828b2471f2e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/getf2.zig +++ /dev/null @@ -1,26 +0,0 @@ -///! The quoted behavior definitions are from -///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const comparef = @import("./comparef.zig"); - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__getf2, "__gekf2"); - symbol(&__gttf2, "__gtkf2"); - } - symbol(&__getf2, "__getf2"); - symbol(&__gttf2, "__gttf2"); -} - -/// "These functions return a value greater than or equal to zero if neither -/// argument is NaN, and a is greater than or equal to b." -fn __getf2(a: f128, b: f128) callconv(.c) i32 { - return @backingInt(comparef.cmpf2(f128, comparef.GE, a, b)); -} - -/// "These functions return a value greater than zero if neither argument is NaN, -/// and a is strictly greater than b." -fn __gttf2(a: f128, b: f128) callconv(.c) i32 { - return __getf2(a, b); -} diff --git a/lib/compiler_rt/gexf2.zig b/lib/compiler_rt/gexf2.zig deleted file mode 100644 index 9f1f356187cdf9c7b85be2d49f9e2e73439f381b..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/gexf2.zig +++ /dev/null @@ -1,15 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const comparef = @import("./comparef.zig"); - -comptime { - symbol(&__gexf2, "__gexf2"); - symbol(&__gtxf2, "__gtxf2"); -} - -fn __gexf2(a: f80, b: f80) callconv(.c) i32 { - return @backingInt(comparef.cmp_f80(comparef.GE, a, b)); -} - -fn __gtxf2(a: f80, b: f80) callconv(.c) i32 { - return __gexf2(a, b); -} diff --git a/lib/compiler_rt/int.zig b/lib/compiler_rt/int.zig index 48c900207bce8946adf6bb9cafe9407b214946d4..e387be858213a7afb575bd3b81f62e016e16a19e 100644 --- a/lib/compiler_rt/int.zig +++ b/lib/compiler_rt/int.zig @@ -36,7 +36,7 @@ comptime { pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 { const d = __divti3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } @@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 { const d = __divdi3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } @@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void { try testing.expect(q == expected_q and r == expected_r); } -const cases__divmoddi4 = - [_][4]i64{ - [_]i64{ 0, 1, 0, 0 }, - [_]i64{ 0, -1, 0, 0 }, - [_]i64{ 2, 1, 2, 0 }, - [_]i64{ 2, -1, -2, 0 }, - [_]i64{ -2, 1, -2, 0 }, - [_]i64{ -2, -1, 2, 0 }, - [_]i64{ 7, 5, 1, 2 }, - [_]i64{ -7, 5, -1, -2 }, - [_]i64{ 19, 5, 3, 4 }, - [_]i64{ 19, -5, -3, 4 }, - [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, - [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, - }; +const cases__divmoddi4 = [_][4]i64{ + [_]i64{ 0, 1, 0, 0 }, + [_]i64{ 0, -1, 0, 0 }, + [_]i64{ 2, 1, 2, 0 }, + [_]i64{ 2, -1, -2, 0 }, + [_]i64{ -2, 1, -2, 0 }, + [_]i64{ -2, -1, 2, 0 }, + [_]i64{ 7, 5, 1, 2 }, + [_]i64{ -7, 5, -1, -2 }, + [_]i64{ 19, 5, 3, 4 }, + [_]i64{ 19, -5, -3, 4 }, + [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, + [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, +}; test "test_divmoddi4" { for (cases__divmoddi4) |case| { @@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 { return udivmod(u64, a, b, maybe_rem); } -test "test_udivmoddi4" { - _ = @import("udivmoddi4_test.zig"); -} - pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 { // Set aside the sign of the quotient. const sign: u64 = @bitCast((a ^ b) >> 63); @@ -209,25 +204,24 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void { pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 { const d = __divsi3(a, b); - rem.* = a -% (d * b); + rem.* = a - d *% b; return d; } -const cases__divmodsi4 = - [_][4]i32{ - [_]i32{ 0, 1, 0, 0 }, - [_]i32{ 0, -1, 0, 0 }, - [_]i32{ 2, 1, 2, 0 }, - [_]i32{ 2, -1, -2, 0 }, - [_]i32{ -2, 1, -2, 0 }, - [_]i32{ -2, -1, 2, 0 }, - [_]i32{ 7, 5, 1, 2 }, - [_]i32{ -7, 5, -1, -2 }, - [_]i32{ 19, 5, 3, 4 }, - [_]i32{ 19, -5, -3, 4 }, - [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, - [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, - }; +const cases__divmodsi4 = [_][4]i32{ + [_]i32{ 0, 1, 0, 0 }, + [_]i32{ 0, -1, 0, 0 }, + [_]i32{ 2, 1, 2, 0 }, + [_]i32{ 2, -1, -2, 0 }, + [_]i32{ -2, 1, -2, 0 }, + [_]i32{ -2, -1, 2, 0 }, + [_]i32{ 7, 5, 1, 2 }, + [_]i32{ -7, 5, -1, -2 }, + [_]i32{ 19, 5, 3, 4 }, + [_]i32{ 19, -5, -3, 4 }, + [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, + [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, +}; fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void { var r: i32 = undefined; @@ -243,7 +237,7 @@ test "test_divmodsi4" { pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 { const d = __udivsi3(a, b); - rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b)))); + rem.* = a - d * b; return d; } @@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void { } pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 { - return n -% __divsi3(n, d) * d; + return n - __divsi3(n, d) *% d; } test "test_modsi3" { @@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void { } pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 { - return n -% __udivsi3(n, d) * d; + return n - __udivsi3(n, d) * d; } test "test_umodsi3" { @@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void { const r: u32 = __umodsi3(a, b); try testing.expect(r == expected_r); } + +test { + _ = @import("udivmodsi4_test.zig"); + _ = @import("udivmoddi4_test.zig"); +} diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig index 5445e7fb7c6d36111d89112350b5bfc9ced375c8..8eb4c2fcbc79f9d254255372062e473443bffdde 100644 --- a/lib/compiler_rt/int_from_float.zig +++ b/lib/compiler_rt/int_from_float.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("std"); const math = std.math; const Log2Int = std.math.Log2Int; @@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; comptime { - symbol(&__fixxfti, "__fixxfti"); symbol(&__fixhfsi, "__fixhfsi"); symbol(&__fixhfdi, "__fixhfdi"); symbol(&__fixhfti, "__fixhfti"); + symbol(&__fixhfei, "__fixhfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2iz, "__aeabi_f2iz"); + symbol(&__aeabi_f2lz, "__aeabi_f2lz"); + symbol(&__aeabi_fixsfti, "__fixsfti"); + } else { + symbol(&__fixsfsi, "__fixsfsi"); + symbol(&__fixsfdi, "__fixsfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixsfdi, "__stoi64"); + symbol(&__fixsfti, "__fixsfti"); + } + symbol(&__fixsfei, "__fixsfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2iz, "__aeabi_d2iz"); + symbol(&__aeabi_d2lz, "__aeabi_d2lz"); + symbol(&__aeabi_fixdfti, "__fixdfti"); + } else { + symbol(&__fixdfsi, "__fixdfsi"); + symbol(&__fixdfdi, "__fixdfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixdfdi, "__dtoi64"); + symbol(&__fixdfti, "__fixdfti"); + } + symbol(&__fixdfei, "__fixdfei"); + + symbol(&__fixxfsi, "__fixxfsi"); + symbol(&__fixxfdi, "__fixxfdi"); + symbol(&__fixxfti, "__fixxfti"); + symbol(&__fixxfei, "__fixxfei"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__fixtfsi, "__fixkfsi"); + symbol(&__fixtfdi, "__fixkfdi"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtoi, "_Qp_qtoi"); + symbol(&_Qp_qtox, "_Qp_qtox"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__fixtfsi, "_Q_qtoi"); + symbol(&__fixtfdi, "_Q_qtoll"); + } else { + symbol(&__fixtfsi, "__fixtfsi"); + symbol(&__fixtfdi, "__fixtfdi"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__fixtfti, "__fixkfti"); + symbol(&__fixtfei, "__fixkfei"); + } else { + symbol(&__fixtfti, "__fixtfti"); + symbol(&__fixtfei, "__fixtfei"); + } +} + +fn __fixhfsi(a: compiler_rt.f16.Abi) callconv(.c) i32 { + return i32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i32_intFromFloat_f16(a: f16) i32 { + return intFromFloat(i32, a); } -pub fn __fixhfti(a: f16) callconv(.c) i128 { +fn __fixhfdi(a: compiler_rt.f16.Abi) callconv(.c) i64 { + return i64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i64_intFromFloat_f16(a: f16) i64 { + return intFromFloat(i64, a); +} + +fn __fixhfti(a: compiler_rt.f16.Abi) callconv(.c) i128 { + return i128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn i128_intFromFloat_f16(a: f16) i128 { return intFromFloat(i128, a); } -fn __fixhfdi(a: f16) callconv(.c) i64 { +fn __fixhfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a)); +} +pub fn signed_intFromFloat_f16(result: []u8, a: f16) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixsfsi(a: compiler_rt.f32.Abi) callconv(.c) i32 { + return i32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 { + return i32_intFromFloat_f32(a); +} +pub fn i32_intFromFloat_f32(a: f32) i32 { + return intFromFloat(i32, a); +} + +fn __fixsfdi(a: compiler_rt.f32.Abi) callconv(.c) i64 { + return i64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 { + return i64_intFromFloat_f32(a); +} +pub fn i64_intFromFloat_f32(a: f32) i64 { return intFromFloat(i64, a); } -fn __fixhfsi(a: f16) callconv(.c) i32 { +fn __fixsfti(a: compiler_rt.f32.Abi) callconv(.c) i128 { + return i128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_fixsfti(_: compiler_rt.f32.Abi) callconv(.naked) i128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r1, r0 + \\ mov r0, sp + \\ bl %[__fixsfti] + \\ pop {r0-r4, pc} + : + : [__fixsfti] "X" (&__fixsfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixsfti] + \\ pop {r0-r4, pc} + : + : [__fixsfti] "X" (&__fixsfti), + ), + } +} +pub fn i128_intFromFloat_f32(a: f32) i128 { + return intFromFloat(i128, a); +} + +fn __fixsfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a)); +} +pub fn signed_intFromFloat_f32(result: []u8, a: f32) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixdfsi(a: compiler_rt.f64.Abi) callconv(.c) i32 { + return i32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 { + return i32_intFromFloat_f64(a); +} +pub fn i32_intFromFloat_f64(a: f64) i32 { return intFromFloat(i32, a); } -pub fn __fixxfti(a: f80) callconv(.c) i128 { +fn __fixdfdi(a: compiler_rt.f64.Abi) callconv(.c) i64 { + return i64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 { + return i64_intFromFloat_f64(a); +} +pub fn i64_intFromFloat_f64(a: f64) i64 { + return intFromFloat(i64, a); +} + +fn __fixdfti(a: compiler_rt.f64.Abi) callconv(.c) i128 { + return i128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_fixdfti(_: compiler_rt.f64.Abi) callconv(.naked) i128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r3, r1 + \\ mov r2, r0 + \\ mov r0, sp + \\ bl %[__fixdfti] + \\ pop {r0-r4, pc} + : + : [__fixdfti] "X" (&__fixdfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixdfti] + \\ pop {r0-r4, pc} + : + : [__fixdfti] "X" (&__fixdfti), + ), + } +} +pub fn i128_intFromFloat_f64(a: f64) i128 { return intFromFloat(i128, a); } -pub inline fn intFromFloat(comptime I: type, a: anytype) I { +fn __fixdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a)); +} +pub fn signed_intFromFloat_f64(result: []u8, a: f64) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixxfsi(a: compiler_rt.f80.Abi) callconv(.c) i32 { + return i32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i32_intFromFloat_f80(a: f80) i32 { + return intFromFloat(i32, a); +} + +fn __fixxfdi(a: compiler_rt.f80.Abi) callconv(.c) i64 { + return i64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i64_intFromFloat_f80(a: f80) i64 { + return intFromFloat(i64, a); +} + +fn __fixxfti(a: compiler_rt.f80.Abi) callconv(.c) i128 { + return i128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn i128_intFromFloat_f80(a: f80) i128 { + return intFromFloat(i128, a); +} + +fn __fixxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a)); +} +pub fn signed_intFromFloat_f80(result: []u8, a: f80) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +fn __fixtfsi(a: compiler_rt.f128.Abi) callconv(.c) i32 { + return i32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoi(a: *const f128) callconv(.c) i32 { + return i32_intFromFloat_f128(a.*); +} +pub fn i32_intFromFloat_f128(a: f128) i32 { + return intFromFloat(i32, a); +} + +fn __fixtfdi(a: compiler_rt.f128.Abi) callconv(.c) i64 { + return i64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtox(a: *const f128) callconv(.c) i64 { + return i64_intFromFloat_f128(a.*); +} +pub fn i64_intFromFloat_f128(a: f128) i64 { + return intFromFloat(i64, a); +} + +fn __fixtfti(a: compiler_rt.f128.Abi) callconv(.c) i128 { + return i128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +pub fn i128_intFromFloat_f128(a: f128) i128 { + return intFromFloat(i128, a); +} + +fn __fixtfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return signed_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a)); +} +pub fn signed_intFromFloat_f128(result: []u8, a: f128) void { + bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); +} + +comptime { + symbol(&__fixunshfsi, "__fixunshfsi"); + symbol(&__fixunshfdi, "__fixunshfdi"); + symbol(&__fixunshfti, "__fixunshfti"); + symbol(&__fixunshfei, "__fixunshfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_f2uiz, "__aeabi_f2uiz"); + symbol(&__aeabi_f2ulz, "__aeabi_f2ulz"); + symbol(&__aeabi_fixunssfti, "__fixunssfti"); + } else { + symbol(&__fixunssfsi, "__fixunssfsi"); + symbol(&__fixunssfdi, "__fixunssfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixunssfdi, "__stou64"); + symbol(&__fixunssfti, "__fixunssfti"); + } + symbol(&__fixunssfei, "__fixunssfei"); + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2uiz, "__aeabi_d2uiz"); + symbol(&__aeabi_d2ulz, "__aeabi_d2ulz"); + symbol(&__aeabi_fixunsdfti, "__fixunsdfti"); + } else { + symbol(&__fixunsdfsi, "__fixunsdfsi"); + symbol(&__fixunsdfdi, "__fixunsdfdi"); + if (compiler_rt.want_windows_arm_abi) symbol(&__fixunsdfdi, "__dtou64"); + symbol(&__fixunsdfti, "__fixunsdfti"); + } + symbol(&__fixunsdfei, "__fixunsdfei"); + + symbol(&__fixunsxfsi, "__fixunsxfsi"); + symbol(&__fixunsxfdi, "__fixunsxfdi"); + symbol(&__fixunsxfti, "__fixunsxfti"); + symbol(&__fixunsxfei, "__fixunsxfei"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__fixunstfsi, "__fixunskfsi"); + symbol(&__fixunstfdi, "__fixunskfdi"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtoui, "_Qp_qtoui"); + symbol(&_Qp_qtoux, "_Qp_qtoux"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__fixunstfsi, "_Q_qtou"); + symbol(&__fixunstfdi, "_Q_qtoull"); + } else { + symbol(&__fixunstfsi, "__fixunstfsi"); + symbol(&__fixunstfdi, "__fixunstfdi"); + } + if (compiler_rt.want_ppc_abi) { + symbol(&__fixunstfti, "__fixunskfti"); + symbol(&__fixunstfei, "__fixunskfei"); + } else { + symbol(&__fixunstfti, "__fixunstfti"); + symbol(&__fixunstfei, "__fixunstfei"); + } +} + +fn __fixunshfsi(a: compiler_rt.f16.Abi) callconv(.c) u32 { + return u32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u32_intFromFloat_f16(a: f16) u32 { + return intFromFloat(u32, a); +} + +fn __fixunshfdi(a: compiler_rt.f16.Abi) callconv(.c) u64 { + return u64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u64_intFromFloat_f16(a: f16) u64 { + return intFromFloat(u64, a); +} + +fn __fixunshfti(a: compiler_rt.f16.Abi) callconv(.c) u128 { + return u128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); +} +pub fn u128_intFromFloat_f16(a: f16) u128 { + return intFromFloat(u128, a); +} + +fn __fixunshfei(r: [*]u8, bits: usize, a: compiler_rt.f16.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f16(r[0..byte_size], compiler_rt.f16.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f16(result: []u8, a: f16) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunssfsi(a: compiler_rt.f32.Abi) callconv(.c) u32 { + return u32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 { + return u32_intFromFloat_f32(a); +} +pub fn u32_intFromFloat_f32(a: f32) u32 { + return intFromFloat(u32, a); +} + +fn __fixunssfdi(a: compiler_rt.f32.Abi) callconv(.c) u64 { + return u64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 { + return u64_intFromFloat_f32(a); +} +pub fn u64_intFromFloat_f32(a: f32) u64 { + return intFromFloat(u64, a); +} + +fn __fixunssfti(a: compiler_rt.f32.Abi) callconv(.c) u128 { + return u128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); +} +fn __aeabi_fixunssfti(_: compiler_rt.f32.Abi) callconv(.naked) u128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r1, r0 + \\ mov r0, sp + \\ bl %[__fixunssfti] + \\ pop {r0-r4, pc} + : + : [__fixunssfti] "X" (&__fixunssfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixunssfti] + \\ pop {r0-r4, pc} + : + : [__fixunssfti] "X" (&__fixunssfti), + ), + } +} +pub fn u128_intFromFloat_f32(a: f32) u128 { + return intFromFloat(u128, a); +} + +fn __fixunssfei(r: [*]u8, bits: usize, a: compiler_rt.f32.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f32(r[0..byte_size], compiler_rt.f32.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f32(result: []u8, a: f32) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunsdfsi(a: compiler_rt.f64.Abi) callconv(.c) u32 { + return u32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 { + return u32_intFromFloat_f64(a); +} +pub fn u32_intFromFloat_f64(a: f64) u32 { + return intFromFloat(u32, a); +} + +fn __fixunsdfdi(a: compiler_rt.f64.Abi) callconv(.c) u64 { + return u64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 { + return u64_intFromFloat_f64(a); +} +pub fn u64_intFromFloat_f64(a: f64) u64 { + return intFromFloat(u64, a); +} + +fn __fixunsdfti(a: compiler_rt.f64.Abi) callconv(.c) u128 { + return u128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); +} +fn __aeabi_fixunsdfti(_: compiler_rt.f64.Abi) callconv(.naked) u128 { + switch (builtin.abi.float()) { + .soft => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r3, r1 + \\ mov r2, r0 + \\ mov r0, sp + \\ bl %[__fixunsdfti] + \\ pop {r0-r4, pc} + : + : [__fixunsdfti] "X" (&__fixunsdfti), + ), + .hard => asm volatile ( + \\ push {r0-r4, lr} + \\ mov r0, sp + \\ bl %[__fixunsdfti] + \\ pop {r0-r4, pc} + : + : [__fixunsdfti] "X" (&__fixunsdfti), + ), + } +} +pub fn u128_intFromFloat_f64(a: f64) u128 { + return intFromFloat(u128, a); +} + +fn __fixunsdfei(r: [*]u8, bits: usize, a: compiler_rt.f64.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f64(r[0..byte_size], compiler_rt.f64.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f64(result: []u8, a: f64) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunsxfsi(a: compiler_rt.f80.Abi) callconv(.c) u32 { + return u32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u32_intFromFloat_f80(a: f80) u32 { + return intFromFloat(u32, a); +} + +fn __fixunsxfdi(a: compiler_rt.f80.Abi) callconv(.c) u64 { + return u64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u64_intFromFloat_f80(a: f80) u64 { + return intFromFloat(u64, a); +} + +fn __fixunsxfti(a: compiler_rt.f80.Abi) callconv(.c) u128 { + return u128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); +} +pub fn u128_intFromFloat_f80(a: f80) u128 { + return intFromFloat(u128, a); +} + +fn __fixunsxfei(r: [*]u8, bits: usize, a: compiler_rt.f80.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f80(r[0..byte_size], compiler_rt.f80.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f80(result: []u8, a: f80) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +fn __fixunstfsi(a: compiler_rt.f128.Abi) callconv(.c) u32 { + return u32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoui(a: *const f128) callconv(.c) u32 { + return u32_intFromFloat_f128(a.*); +} +pub fn u32_intFromFloat_f128(a: f128) u32 { + return intFromFloat(u32, a); +} + +fn __fixunstfdi(a: compiler_rt.f128.Abi) callconv(.c) u64 { + return u64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +fn _Qp_qtoux(a: *const f128) callconv(.c) u64 { + return u64_intFromFloat_f128(a.*); +} +pub fn u64_intFromFloat_f128(a: f128) u64 { + return intFromFloat(u64, a); +} + +fn __fixunstfti(a: compiler_rt.f128.Abi) callconv(.c) u128 { + return u128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); +} +pub fn u128_intFromFloat_f128(a: f128) u128 { + return intFromFloat(u128, a); +} + +fn __fixunstfei(r: [*]u8, bits: usize, a: compiler_rt.f128.Abi) callconv(.c) void { + const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits)); + return unsigned_intFromFloat_f128(r[0..byte_size], compiler_rt.f128.fromAbi(a)); +} +pub fn unsigned_intFromFloat_f128(result: []u8, a: f128) void { + bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); +} + +inline fn intFromFloat(comptime I: type, a: anytype) I { const F = @TypeOf(a); const float_bits = @typeInfo(F).float.bits; const int_bits = @typeInfo(I).int.bits; @@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I { return result; } -pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, result: []u32, a: anytype) void { +inline fn bigIntFromFloat(comptime signedness: std.lang.Signedness, result: []u32, a: anytype) void { + const endian = builtin.cpu.arch.endian(); switch (result.len) { 0 => return, inline 1...4 => |limbs_len| { const I = @Int(signedness, 32 * limbs_len); const low_to_high: [limbs_len]u32 = @bitCast(@as(I, @intFromFloat(a))); - result[0..limbs_len].* = switch (@import("builtin").cpu.arch.endian()) { + result[0..limbs_len].* = switch (endian) { .little => low_to_high, .big => switch (limbs_len) { 1 => .{low_to_high[0]}, @@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul }); switch (signedness) { .signed => { - const endian = @import("builtin").cpu.arch.endian(); const exponent_limb = switch (endian) { .little => exponent / 32, .big => result.len - 1 - exponent / 32, diff --git a/lib/compiler_rt/int_from_float_test.zig b/lib/compiler_rt/int_from_float_test.zig index de96954dd15474c6d9f9c5109c717b3d5b6417c2..23f04e2b88a2a01756ad608cb2d9774b54d38c25 100644 --- a/lib/compiler_rt/int_from_float_test.zig +++ b/lib/compiler_rt/int_from_float_test.zig @@ -2,1023 +2,1039 @@ const std = @import("std"); const testing = std.testing; const math = std.math; -const __fixunshfti = @import("fixunshfti.zig").__fixunshfti; -const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti; - -// Conversion from f32 -const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; -const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; -const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; -const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; -const __fixsfti = @import("fixsfti.zig").__fixsfti; -const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; -const __fixsfei = @import("fixsfei.zig").__fixsfei; -const __fixunssfei = @import("fixunssfei.zig").__fixunssfei; - -// Conversion from f64 -const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; -const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; -const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; -const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; -const __fixdfti = @import("fixdfti.zig").__fixdfti; -const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; -const __fixdfei = @import("fixdfei.zig").__fixdfei; -const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei; - -// Conversion from f128 -const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; -const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; -const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; -const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; -const __fixtfti = @import("fixtfti.zig").__fixtfti; -const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; - -fn test__fixsfsi(a: f32, expected: i32) !void { - const x = __fixsfsi(a); +const impl = @import("int_from_float.zig"); + +const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16; +const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16; +const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16; +const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16; +const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16; +const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16; +const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16; +const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16; + +const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32; +const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32; +const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32; +const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32; +const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32; +const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32; +const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32; +const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32; + +const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64; +const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64; +const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64; +const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64; +const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64; +const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64; +const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64; +const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64; + +const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80; +const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80; +const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80; +const u64_intFromFloat_f80 = impl.u64_intFromFloat_f80; +const i128_intFromFloat_f80 = impl.i128_intFromFloat_f80; +const u128_intFromFloat_f80 = impl.u128_intFromFloat_f80; +const signed_intFromFloat_f80 = impl.signed_intFromFloat_f80; +const unsigned_intFromFloat_f80 = impl.unsigned_intFromFloat_f80; + +const i32_intFromFloat_f128 = impl.i32_intFromFloat_f128; +const u32_intFromFloat_f128 = impl.u32_intFromFloat_f128; +const i64_intFromFloat_f128 = impl.i64_intFromFloat_f128; +const u64_intFromFloat_f128 = impl.u64_intFromFloat_f128; +const i128_intFromFloat_f128 = impl.i128_intFromFloat_f128; +const u128_intFromFloat_f128 = impl.u128_intFromFloat_f128; +const signed_intFromFloat_f128 = impl.signed_intFromFloat_f128; +const unsigned_intFromFloat_f128 = impl.unsigned_intFromFloat_f128; + +fn test_i32_intFromFloat_f32(a: f32, expected: i32) !void { + const x = i32_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfsi(a: f32, expected: u32) !void { - const x = __fixunssfsi(a); +fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void { + const x = u32_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfsi" { - try test__fixsfsi(-math.floatMax(f32), math.minInt(i32)); - - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixsfsi(-0x1.000000p+31, -0x80000000); - try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); - try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixsfsi(-2.01, -2); - try test__fixsfsi(-2.0, -2); - try test__fixsfsi(-1.99, -1); - try test__fixsfsi(-1.0, -1); - try test__fixsfsi(-0.99, 0); - try test__fixsfsi(-0.5, 0); - - try test__fixsfsi(-math.floatMin(f32), 0); - try test__fixsfsi(0.0, 0); - try test__fixsfsi(math.floatMin(f32), 0); - try test__fixsfsi(0.5, 0); - try test__fixsfsi(0.99, 0); - try test__fixsfsi(1.0, 1); - try test__fixsfsi(1.5, 1); - try test__fixsfsi(1.99, 1); - try test__fixsfsi(2.0, 2); - try test__fixsfsi(2.01, 2); - - try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); - try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixsfsi(math.floatMax(f32), math.maxInt(i32)); -} - -test "fixunssfsi" { - try test__fixunssfsi(0.0, 0); - - try test__fixunssfsi(0.5, 0); - try test__fixunssfsi(0.99, 0); - try test__fixunssfsi(1.0, 1); - try test__fixunssfsi(1.5, 1); - try test__fixunssfsi(1.99, 1); - try test__fixunssfsi(2.0, 2); - try test__fixunssfsi(2.01, 2); - try test__fixunssfsi(-0.5, 0); - try test__fixunssfsi(-0.99, 0); - - try test__fixunssfsi(-1.0, 0); - try test__fixunssfsi(-1.5, 0); - try test__fixunssfsi(-1.99, 0); - try test__fixunssfsi(-2.0, 0); - try test__fixunssfsi(-2.01, 0); - - try test__fixunssfsi(0x1.000000p+31, 0x80000000); - try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF); - try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00); - try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - - try test__fixunssfsi(-0x1.FFFFFEp+30, 0); - try test__fixunssfsi(-0x1.FFFFFCp+30, 0); -} - -fn test__fixsfdi(a: f32, expected: i64) !void { - const x = __fixsfdi(a); +test i32_intFromFloat_f32 { + try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32)); + + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); + try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i32_intFromFloat_f32(-2.01, -2); + try test_i32_intFromFloat_f32(-2.0, -2); + try test_i32_intFromFloat_f32(-1.99, -1); + try test_i32_intFromFloat_f32(-1.0, -1); + try test_i32_intFromFloat_f32(-0.99, 0); + try test_i32_intFromFloat_f32(-0.5, 0); + + try test_i32_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i32_intFromFloat_f32(0.0, 0); + try test_i32_intFromFloat_f32(math.floatMin(f32), 0); + try test_i32_intFromFloat_f32(0.5, 0); + try test_i32_intFromFloat_f32(0.99, 0); + try test_i32_intFromFloat_f32(1.0, 1); + try test_i32_intFromFloat_f32(1.5, 1); + try test_i32_intFromFloat_f32(1.99, 1); + try test_i32_intFromFloat_f32(2.0, 2); + try test_i32_intFromFloat_f32(2.01, 2); + + try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32)); +} + +test u32_intFromFloat_f32 { + try test_u32_intFromFloat_f32(0.0, 0); + + try test_u32_intFromFloat_f32(0.5, 0); + try test_u32_intFromFloat_f32(0.99, 0); + try test_u32_intFromFloat_f32(1.0, 1); + try test_u32_intFromFloat_f32(1.5, 1); + try test_u32_intFromFloat_f32(1.99, 1); + try test_u32_intFromFloat_f32(2.0, 2); + try test_u32_intFromFloat_f32(2.01, 2); + try test_u32_intFromFloat_f32(-0.5, 0); + try test_u32_intFromFloat_f32(-0.99, 0); + + try test_u32_intFromFloat_f32(-1.0, 0); + try test_u32_intFromFloat_f32(-1.5, 0); + try test_u32_intFromFloat_f32(-1.99, 0); + try test_u32_intFromFloat_f32(-2.0, 0); + try test_u32_intFromFloat_f32(-2.01, 0); + + try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000); + try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF); + try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00); + try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + + try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0); + try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0); +} + +fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void { + const x = i64_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfdi(a: f32, expected: u64) !void { - const x = __fixunssfdi(a); +fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void { + const x = u64_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfdi" { - try test__fixsfdi(-math.floatMax(f32), math.minInt(i64)); - - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); - - try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); - try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixsfdi(-2.01, -2); - try test__fixsfdi(-2.0, -2); - try test__fixsfdi(-1.99, -1); - try test__fixsfdi(-1.0, -1); - try test__fixsfdi(-0.99, 0); - try test__fixsfdi(-0.5, 0); - try test__fixsfdi(-math.floatMin(f32), 0); - try test__fixsfdi(0.0, 0); - try test__fixsfdi(math.floatMin(f32), 0); - try test__fixsfdi(0.5, 0); - try test__fixsfdi(0.99, 0); - try test__fixsfdi(1.0, 1); - try test__fixsfdi(1.5, 1); - try test__fixsfdi(1.99, 1); - try test__fixsfdi(2.0, 2); - try test__fixsfdi(2.01, 2); - - try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixsfdi(math.floatMax(f32), math.maxInt(i64)); -} - -test "fixunssfdi" { - try test__fixunssfdi(0.0, 0); - - try test__fixunssfdi(0.5, 0); - try test__fixunssfdi(0.99, 0); - try test__fixunssfdi(1.0, 1); - try test__fixunssfdi(1.5, 1); - try test__fixunssfdi(1.99, 1); - try test__fixunssfdi(2.0, 2); - try test__fixunssfdi(2.01, 2); - try test__fixunssfdi(-0.5, 0); - try test__fixunssfdi(-0.99, 0); - - try test__fixunssfdi(-1.0, 0); - try test__fixunssfdi(-1.5, 0); - try test__fixunssfdi(-1.99, 0); - try test__fixunssfdi(-2.0, 0); - try test__fixunssfdi(-2.01, 0); - - try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000); - try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000); - try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000); - try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000); -} - -fn test__fixsfti(a: f32, expected: i128) !void { - const x = __fixsfti(a); +test i64_intFromFloat_f32 { + try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64)); + + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); + + try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i64_intFromFloat_f32(-2.01, -2); + try test_i64_intFromFloat_f32(-2.0, -2); + try test_i64_intFromFloat_f32(-1.99, -1); + try test_i64_intFromFloat_f32(-1.0, -1); + try test_i64_intFromFloat_f32(-0.99, 0); + try test_i64_intFromFloat_f32(-0.5, 0); + try test_i64_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i64_intFromFloat_f32(0.0, 0); + try test_i64_intFromFloat_f32(math.floatMin(f32), 0); + try test_i64_intFromFloat_f32(0.5, 0); + try test_i64_intFromFloat_f32(0.99, 0); + try test_i64_intFromFloat_f32(1.0, 1); + try test_i64_intFromFloat_f32(1.5, 1); + try test_i64_intFromFloat_f32(1.99, 1); + try test_i64_intFromFloat_f32(2.0, 2); + try test_i64_intFromFloat_f32(2.01, 2); + + try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64)); +} + +test u64_intFromFloat_f32 { + try test_u64_intFromFloat_f32(0.0, 0); + + try test_u64_intFromFloat_f32(0.5, 0); + try test_u64_intFromFloat_f32(0.99, 0); + try test_u64_intFromFloat_f32(1.0, 1); + try test_u64_intFromFloat_f32(1.5, 1); + try test_u64_intFromFloat_f32(1.99, 1); + try test_u64_intFromFloat_f32(2.0, 2); + try test_u64_intFromFloat_f32(2.01, 2); + try test_u64_intFromFloat_f32(-0.5, 0); + try test_u64_intFromFloat_f32(-0.99, 0); + + try test_u64_intFromFloat_f32(-1.0, 0); + try test_u64_intFromFloat_f32(-1.5, 0); + try test_u64_intFromFloat_f32(-1.99, 0); + try test_u64_intFromFloat_f32(-2.0, 0); + try test_u64_intFromFloat_f32(-2.01, 0); + + try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); + try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); + try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); +} + +fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void { + const x = i128_intFromFloat_f32(a); try testing.expect(x == expected); } -fn test__fixunssfti(a: f32, expected: u128) !void { - const x = __fixunssfti(a); +fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void { + const x = u128_intFromFloat_f32(a); try testing.expect(x == expected); } -test "fixsfti" { - try test__fixsfti(-math.floatMax(f32), math.minInt(i128)); - - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); - try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); - try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); - - try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); - - try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); - try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixsfti(-0x1.000000p+31, -0x80000000); - try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); - try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixsfti(-2.01, -2); - try test__fixsfti(-2.0, -2); - try test__fixsfti(-1.99, -1); - try test__fixsfti(-1.0, -1); - try test__fixsfti(-0.99, 0); - try test__fixsfti(-0.5, 0); - try test__fixsfti(-math.floatMin(f32), 0); - try test__fixsfti(0.0, 0); - try test__fixsfti(math.floatMin(f32), 0); - try test__fixsfti(0.5, 0); - try test__fixsfti(0.99, 0); - try test__fixsfti(1.0, 1); - try test__fixsfti(1.5, 1); - try test__fixsfti(1.99, 1); - try test__fixsfti(2.0, 2); - try test__fixsfti(2.01, 2); - - try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixsfti(0x1.FFFFFFp+30, 0x80000000); - try test__fixsfti(0x1.000000p+31, 0x80000000); - - try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); - - try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); - try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); - - try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); - try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); - try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); - - try test__fixsfti(math.floatMax(f32), math.maxInt(i128)); -} - -test "fixunssfti" { - try test__fixunssfti(0.0, 0); - - try test__fixunssfti(0.5, 0); - try test__fixunssfti(0.99, 0); - try test__fixunssfti(1.0, 1); - try test__fixunssfti(1.5, 1); - try test__fixunssfti(1.99, 1); - try test__fixunssfti(2.0, 2); - try test__fixunssfti(2.01, 2); - try test__fixunssfti(-0.5, 0); - try test__fixunssfti(-0.99, 0); - - try test__fixunssfti(-1.0, 0); - try test__fixunssfti(-1.5, 0); - try test__fixunssfti(-1.99, 0); - try test__fixunssfti(-2.0, 0); - try test__fixunssfti(-2.01, 0); - - try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000); - try test__fixunssfti(0x1.000000p+63, 0x8000000000000000); - try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); - try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000); - try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); - try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); - - try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000); - try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000); - try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000); - try test__fixunssfti(math.inf(f32), math.maxInt(u128)); -} - -fn test_fixsfei(comptime T: type, expected: T, a: f32) !void { +test i128_intFromFloat_f32 { + try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128)); + + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); + + try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); + + try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); + try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i128_intFromFloat_f32(-2.01, -2); + try test_i128_intFromFloat_f32(-2.0, -2); + try test_i128_intFromFloat_f32(-1.99, -1); + try test_i128_intFromFloat_f32(-1.0, -1); + try test_i128_intFromFloat_f32(-0.99, 0); + try test_i128_intFromFloat_f32(-0.5, 0); + try test_i128_intFromFloat_f32(-math.floatMin(f32), 0); + try test_i128_intFromFloat_f32(0.0, 0); + try test_i128_intFromFloat_f32(math.floatMin(f32), 0); + try test_i128_intFromFloat_f32(0.5, 0); + try test_i128_intFromFloat_f32(0.99, 0); + try test_i128_intFromFloat_f32(1.0, 1); + try test_i128_intFromFloat_f32(1.5, 1); + try test_i128_intFromFloat_f32(1.99, 1); + try test_i128_intFromFloat_f32(2.0, 2); + try test_i128_intFromFloat_f32(2.01, 2); + + try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000); + try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000); + + try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); + try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128)); +} + +test u128_intFromFloat_f32 { + try test_u128_intFromFloat_f32(0.0, 0); + + try test_u128_intFromFloat_f32(0.5, 0); + try test_u128_intFromFloat_f32(0.99, 0); + try test_u128_intFromFloat_f32(1.0, 1); + try test_u128_intFromFloat_f32(1.5, 1); + try test_u128_intFromFloat_f32(1.99, 1); + try test_u128_intFromFloat_f32(2.0, 2); + try test_u128_intFromFloat_f32(2.01, 2); + try test_u128_intFromFloat_f32(-0.5, 0); + try test_u128_intFromFloat_f32(-0.99, 0); + + try test_u128_intFromFloat_f32(-1.0, 0); + try test_u128_intFromFloat_f32(-1.5, 0); + try test_u128_intFromFloat_f32(-1.99, 0); + try test_u128_intFromFloat_f32(-2.0, 0); + try test_u128_intFromFloat_f32(-2.01, 0); + + try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); + try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); + try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); + + try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000); + try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000); + try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000); + try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128)); +} + +fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void { const int = @typeInfo(T).int; var actual: T = undefined; _ = switch (int.signedness) { - .signed => __fixsfei, - .unsigned => __fixunssfei, - }(@ptrCast(&actual), int.bits, a); + .signed => signed_intFromFloat_f32, + .unsigned => unsigned_intFromFloat_f32, + }(@ptrCast(&actual), a); try testing.expect(expected == actual); } -test "fixsfei" { - try test_fixsfei(i256, -1 << 127, -0x1p127); - try test_fixsfei(i256, -1 << 100, -0x1p100); - try test_fixsfei(i256, -1 << 50, -0x1p50); - try test_fixsfei(i256, -1 << 1, -0x1p1); - try test_fixsfei(i256, -1 << 0, -0x1p0); - try test_fixsfei(i256, 0, 0); - try test_fixsfei(i256, 1 << 0, 0x1p0); - try test_fixsfei(i256, 1 << 1, 0x1p1); - try test_fixsfei(i256, 1 << 50, 0x1p50); - try test_fixsfei(i256, 1 << 100, 0x1p100); - try test_fixsfei(i256, 1 << 127, 0x1p127); +test signed_intFromFloat_f32 { + try test_intFromFloat_f32(i256, -1 << 127, -0x1p127); + try test_intFromFloat_f32(i256, -1 << 100, -0x1p100); + try test_intFromFloat_f32(i256, -1 << 50, -0x1p50); + try test_intFromFloat_f32(i256, -1 << 1, -0x1p1); + try test_intFromFloat_f32(i256, -1 << 0, -0x1p0); + try test_intFromFloat_f32(i256, 0, 0); + try test_intFromFloat_f32(i256, 1 << 0, 0x1p0); + try test_intFromFloat_f32(i256, 1 << 1, 0x1p1); + try test_intFromFloat_f32(i256, 1 << 50, 0x1p50); + try test_intFromFloat_f32(i256, 1 << 100, 0x1p100); + try test_intFromFloat_f32(i256, 1 << 127, 0x1p127); } -test "fixunsfei" { - try test_fixsfei(u256, 0, 0); - try test_fixsfei(u256, 1 << 0, 0x1p0); - try test_fixsfei(u256, 1 << 1, 0x1p1); - try test_fixsfei(u256, 1 << 50, 0x1p50); - try test_fixsfei(u256, 1 << 100, 0x1p100); - try test_fixsfei(u256, 1 << 127, 0x1p127); +test unsigned_intFromFloat_f32 { + try test_intFromFloat_f32(u256, 0, 0); + try test_intFromFloat_f32(u256, 1 << 0, 0x1p0); + try test_intFromFloat_f32(u256, 1 << 1, 0x1p1); + try test_intFromFloat_f32(u256, 1 << 50, 0x1p50); + try test_intFromFloat_f32(u256, 1 << 100, 0x1p100); + try test_intFromFloat_f32(u256, 1 << 127, 0x1p127); } -fn test__fixdfsi(a: f64, expected: i32) !void { - const x = __fixdfsi(a); +fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void { + const x = i32_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfsi(a: f64, expected: u32) !void { - const x = __fixunsdfsi(a); +fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void { + const x = u32_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfsi" { - try test__fixdfsi(-math.floatMax(f64), math.minInt(i32)); - - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixdfsi(-0x1.000000p+31, -0x80000000); - try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - - try test__fixdfsi(-2.01, -2); - try test__fixdfsi(-2.0, -2); - try test__fixdfsi(-1.99, -1); - try test__fixdfsi(-1.0, -1); - try test__fixdfsi(-0.99, 0); - try test__fixdfsi(-0.5, 0); - try test__fixdfsi(-math.floatMin(f64), 0); - try test__fixdfsi(0.0, 0); - try test__fixdfsi(math.floatMin(f64), 0); - try test__fixdfsi(0.5, 0); - try test__fixdfsi(0.99, 0); - try test__fixdfsi(1.0, 1); - try test__fixdfsi(1.5, 1); - try test__fixdfsi(1.99, 1); - try test__fixdfsi(2.0, 2); - try test__fixdfsi(2.01, 2); - - try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixdfsi(math.floatMax(f64), math.maxInt(i32)); -} - -test "fixunsdfsi" { - try test__fixunsdfsi(0.0, 0); - - try test__fixunsdfsi(0.5, 0); - try test__fixunsdfsi(0.99, 0); - try test__fixunsdfsi(1.0, 1); - try test__fixunsdfsi(1.5, 1); - try test__fixunsdfsi(1.99, 1); - try test__fixunsdfsi(2.0, 2); - try test__fixunsdfsi(2.01, 2); - try test__fixunsdfsi(-0.5, 0); - try test__fixunsdfsi(-0.99, 0); - try test__fixunsdfsi(-1.0, 0); - try test__fixunsdfsi(-1.5, 0); - try test__fixunsdfsi(-1.99, 0); - try test__fixunsdfsi(-2.0, 0); - try test__fixunsdfsi(-2.01, 0); - - try test__fixunsdfsi(0x1.000000p+31, 0x80000000); - try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF); - try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00); - try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - - try test__fixunsdfsi(-0x1.FFFFFEp+30, 0); - try test__fixunsdfsi(-0x1.FFFFFCp+30, 0); - - try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF); - try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); - try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); -} - -fn test__fixdfdi(a: f64, expected: i64) !void { - const x = __fixdfdi(a); +test i32_intFromFloat_f64 { + try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32)); + + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80); + + try test_i32_intFromFloat_f64(-2.01, -2); + try test_i32_intFromFloat_f64(-2.0, -2); + try test_i32_intFromFloat_f64(-1.99, -1); + try test_i32_intFromFloat_f64(-1.0, -1); + try test_i32_intFromFloat_f64(-0.99, 0); + try test_i32_intFromFloat_f64(-0.5, 0); + try test_i32_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i32_intFromFloat_f64(0.0, 0); + try test_i32_intFromFloat_f64(math.floatMin(f64), 0); + try test_i32_intFromFloat_f64(0.5, 0); + try test_i32_intFromFloat_f64(0.99, 0); + try test_i32_intFromFloat_f64(1.0, 1); + try test_i32_intFromFloat_f64(1.5, 1); + try test_i32_intFromFloat_f64(1.99, 1); + try test_i32_intFromFloat_f64(2.0, 2); + try test_i32_intFromFloat_f64(2.01, 2); + + try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32)); +} + +test u32_intFromFloat_f64 { + try test_u32_intFromFloat_f64(0.0, 0); + + try test_u32_intFromFloat_f64(0.5, 0); + try test_u32_intFromFloat_f64(0.99, 0); + try test_u32_intFromFloat_f64(1.0, 1); + try test_u32_intFromFloat_f64(1.5, 1); + try test_u32_intFromFloat_f64(1.99, 1); + try test_u32_intFromFloat_f64(2.0, 2); + try test_u32_intFromFloat_f64(2.01, 2); + try test_u32_intFromFloat_f64(-0.5, 0); + try test_u32_intFromFloat_f64(-0.99, 0); + try test_u32_intFromFloat_f64(-1.0, 0); + try test_u32_intFromFloat_f64(-1.5, 0); + try test_u32_intFromFloat_f64(-1.99, 0); + try test_u32_intFromFloat_f64(-2.0, 0); + try test_u32_intFromFloat_f64(-2.01, 0); + + try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000); + try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00); + try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00); + + try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0); + try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0); + + try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); + try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); +} + +fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void { + const x = i64_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfdi(a: f64, expected: u64) !void { - const x = __fixunsdfdi(a); +fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void { + const x = u64_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfdi" { - try test__fixdfdi(-math.floatMax(f64), math.minInt(i64)); - - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixdfdi(-2.01, -2); - try test__fixdfdi(-2.0, -2); - try test__fixdfdi(-1.99, -1); - try test__fixdfdi(-1.0, -1); - try test__fixdfdi(-0.99, 0); - try test__fixdfdi(-0.5, 0); - try test__fixdfdi(-math.floatMin(f64), 0); - try test__fixdfdi(0.0, 0); - try test__fixdfdi(math.floatMin(f64), 0); - try test__fixdfdi(0.5, 0); - try test__fixdfdi(0.99, 0); - try test__fixdfdi(1.0, 1); - try test__fixdfdi(1.5, 1); - try test__fixdfdi(1.99, 1); - try test__fixdfdi(2.0, 2); - try test__fixdfdi(2.01, 2); - - try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixdfdi(math.floatMax(f64), math.maxInt(i64)); -} - -test "fixunsdfdi" { - try test__fixunsdfdi(0.0, 0); - try test__fixunsdfdi(0.5, 0); - try test__fixunsdfdi(0.99, 0); - try test__fixunsdfdi(1.0, 1); - try test__fixunsdfdi(1.5, 1); - try test__fixunsdfdi(1.99, 1); - try test__fixunsdfdi(2.0, 2); - try test__fixunsdfdi(2.01, 2); - try test__fixunsdfdi(-0.5, 0); - try test__fixunsdfdi(-0.99, 0); - try test__fixunsdfdi(-1.0, 0); - try test__fixunsdfdi(-1.5, 0); - try test__fixunsdfdi(-1.99, 0); - try test__fixunsdfdi(-2.0, 0); - try test__fixunsdfdi(-2.01, 0); - - try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunsdfdi(-0x1.FFFFFEp+62, 0); - try test__fixunsdfdi(-0x1.FFFFFCp+62, 0); - - try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); - try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0); -} - -fn test__fixdfti(a: f64, expected: i128) !void { - const x = __fixdfti(a); +test i64_intFromFloat_f64 { + try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64)); + + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i64_intFromFloat_f64(-2.01, -2); + try test_i64_intFromFloat_f64(-2.0, -2); + try test_i64_intFromFloat_f64(-1.99, -1); + try test_i64_intFromFloat_f64(-1.0, -1); + try test_i64_intFromFloat_f64(-0.99, 0); + try test_i64_intFromFloat_f64(-0.5, 0); + try test_i64_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i64_intFromFloat_f64(0.0, 0); + try test_i64_intFromFloat_f64(math.floatMin(f64), 0); + try test_i64_intFromFloat_f64(0.5, 0); + try test_i64_intFromFloat_f64(0.99, 0); + try test_i64_intFromFloat_f64(1.0, 1); + try test_i64_intFromFloat_f64(1.5, 1); + try test_i64_intFromFloat_f64(1.99, 1); + try test_i64_intFromFloat_f64(2.0, 2); + try test_i64_intFromFloat_f64(2.01, 2); + + try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64)); +} + +test u64_intFromFloat_f64 { + try test_u64_intFromFloat_f64(0.0, 0); + try test_u64_intFromFloat_f64(0.5, 0); + try test_u64_intFromFloat_f64(0.99, 0); + try test_u64_intFromFloat_f64(1.0, 1); + try test_u64_intFromFloat_f64(1.5, 1); + try test_u64_intFromFloat_f64(1.99, 1); + try test_u64_intFromFloat_f64(2.0, 2); + try test_u64_intFromFloat_f64(2.01, 2); + try test_u64_intFromFloat_f64(-0.5, 0); + try test_u64_intFromFloat_f64(-0.99, 0); + try test_u64_intFromFloat_f64(-1.0, 0); + try test_u64_intFromFloat_f64(-1.5, 0); + try test_u64_intFromFloat_f64(-1.99, 0); + try test_u64_intFromFloat_f64(-2.0, 0); + try test_u64_intFromFloat_f64(-2.01, 0); + + try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0); + try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0); + + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); + try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); +} + +fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void { + const x = i128_intFromFloat_f64(a); try testing.expect(x == expected); } -fn test__fixunsdfti(a: f64, expected: u128) !void { - const x = __fixunsdfti(a); +fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void { + const x = u128_intFromFloat_f64(a); try testing.expect(x == expected); } -test "fixdfti" { - try test__fixdfti(-math.floatMax(f64), math.minInt(i128)); - - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); - - try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); - try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); - - try test__fixdfti(-2.01, -2); - try test__fixdfti(-2.0, -2); - try test__fixdfti(-1.99, -1); - try test__fixdfti(-1.0, -1); - try test__fixdfti(-0.99, 0); - try test__fixdfti(-0.5, 0); - try test__fixdfti(-math.floatMin(f64), 0); - try test__fixdfti(0.0, 0); - try test__fixdfti(math.floatMin(f64), 0); - try test__fixdfti(0.5, 0); - try test__fixdfti(0.99, 0); - try test__fixdfti(1.0, 1); - try test__fixdfti(1.5, 1); - try test__fixdfti(1.99, 1); - try test__fixdfti(2.0, 2); - try test__fixdfti(2.01, 2); - - try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); - - try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); - - try test__fixdfti(math.floatMax(f64), math.maxInt(i128)); -} - -test "fixunsdfti" { - try test__fixunsdfti(0.0, 0); - - try test__fixunsdfti(0.5, 0); - try test__fixunsdfti(0.99, 0); - try test__fixunsdfti(1.0, 1); - try test__fixunsdfti(1.5, 1); - try test__fixunsdfti(1.99, 1); - try test__fixunsdfti(2.0, 2); - try test__fixunsdfti(2.01, 2); - try test__fixunsdfti(-0.5, 0); - try test__fixunsdfti(-0.99, 0); - try test__fixunsdfti(-1.0, 0); - try test__fixunsdfti(-1.5, 0); - try test__fixunsdfti(-1.99, 0); - try test__fixunsdfti(-2.0, 0); - try test__fixunsdfti(-2.01, 0); - - try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunsdfti(-0x1.FFFFFEp+62, 0); - try test__fixunsdfti(-0x1.FFFFFCp+62, 0); - - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); - try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); - try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0); -} - -fn test_fixdfei(comptime T: type, expected: T, a: f64) !void { +test i128_intFromFloat_f64 { + try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128)); + + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); + + try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800); + try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f64(-2.01, -2); + try test_i128_intFromFloat_f64(-2.0, -2); + try test_i128_intFromFloat_f64(-1.99, -1); + try test_i128_intFromFloat_f64(-1.0, -1); + try test_i128_intFromFloat_f64(-0.99, 0); + try test_i128_intFromFloat_f64(-0.5, 0); + try test_i128_intFromFloat_f64(-math.floatMin(f64), 0); + try test_i128_intFromFloat_f64(0.0, 0); + try test_i128_intFromFloat_f64(math.floatMin(f64), 0); + try test_i128_intFromFloat_f64(0.5, 0); + try test_i128_intFromFloat_f64(0.99, 0); + try test_i128_intFromFloat_f64(1.0, 1); + try test_i128_intFromFloat_f64(1.5, 1); + try test_i128_intFromFloat_f64(1.99, 1); + try test_i128_intFromFloat_f64(2.0, 2); + try test_i128_intFromFloat_f64(2.01, 2); + + try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128)); +} + +test u128_intFromFloat_f64 { + try test_u128_intFromFloat_f64(0.0, 0); + + try test_u128_intFromFloat_f64(0.5, 0); + try test_u128_intFromFloat_f64(0.99, 0); + try test_u128_intFromFloat_f64(1.0, 1); + try test_u128_intFromFloat_f64(1.5, 1); + try test_u128_intFromFloat_f64(1.99, 1); + try test_u128_intFromFloat_f64(2.0, 2); + try test_u128_intFromFloat_f64(2.01, 2); + try test_u128_intFromFloat_f64(-0.5, 0); + try test_u128_intFromFloat_f64(-0.99, 0); + try test_u128_intFromFloat_f64(-1.0, 0); + try test_u128_intFromFloat_f64(-1.5, 0); + try test_u128_intFromFloat_f64(-1.99, 0); + try test_u128_intFromFloat_f64(-2.0, 0); + try test_u128_intFromFloat_f64(-2.01, 0); + + try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0); + try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0); + + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); + try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); + try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); +} + +fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void { const int = @typeInfo(T).int; var actual: T = undefined; _ = switch (int.signedness) { - .signed => __fixdfei, - .unsigned => __fixunsdfei, - }(@ptrCast(&actual), int.bits, a); + .signed => signed_intFromFloat_f64, + .unsigned => unsigned_intFromFloat_f64, + }(@ptrCast(&actual), a); try testing.expect(expected == actual); } -test "fixdfei" { - try test_fixdfei(i256, -1 << 255, -0x1p255); - try test_fixdfei(i256, -1 << 127, -0x1p127); - try test_fixdfei(i256, -1 << 100, -0x1p100); - try test_fixdfei(i256, -1 << 50, -0x1p50); - try test_fixdfei(i256, -1 << 1, -0x1p1); - try test_fixdfei(i256, -1 << 0, -0x1p0); - try test_fixdfei(i256, 0, 0); - try test_fixdfei(i256, 1 << 0, 0x1p0); - try test_fixdfei(i256, 1 << 1, 0x1p1); - try test_fixdfei(i256, 1 << 50, 0x1p50); - try test_fixdfei(i256, 1 << 100, 0x1p100); - try test_fixdfei(i256, 1 << 127, 0x1p127); - try test_fixdfei(i256, 1 << 254, 0x1p254); -} - -test "fixundfei" { - try test_fixdfei(u256, 0, 0); - try test_fixdfei(u256, 1 << 0, 0x1p0); - try test_fixdfei(u256, 1 << 1, 0x1p1); - try test_fixdfei(u256, 1 << 50, 0x1p50); - try test_fixdfei(u256, 1 << 100, 0x1p100); - try test_fixdfei(u256, 1 << 127, 0x1p127); - try test_fixdfei(u256, 1 << 255, 0x1p255); -} - -fn test__fixtfsi(a: f128, expected: i32) !void { - const x = __fixtfsi(a); - try testing.expect(x == expected); +test signed_intFromFloat_f64 { + try test_intFromFloat_f64(i256, -1 << 255, -0x1p255); + try test_intFromFloat_f64(i256, -1 << 127, -0x1p127); + try test_intFromFloat_f64(i256, -1 << 100, -0x1p100); + try test_intFromFloat_f64(i256, -1 << 50, -0x1p50); + try test_intFromFloat_f64(i256, -1 << 1, -0x1p1); + try test_intFromFloat_f64(i256, -1 << 0, -0x1p0); + try test_intFromFloat_f64(i256, 0, 0); + try test_intFromFloat_f64(i256, 1 << 0, 0x1p0); + try test_intFromFloat_f64(i256, 1 << 1, 0x1p1); + try test_intFromFloat_f64(i256, 1 << 50, 0x1p50); + try test_intFromFloat_f64(i256, 1 << 100, 0x1p100); + try test_intFromFloat_f64(i256, 1 << 127, 0x1p127); + try test_intFromFloat_f64(i256, 1 << 254, 0x1p254); } -fn test__fixunstfsi(a: f128, expected: u32) !void { - const x = __fixunstfsi(a); - try testing.expect(x == expected); +test unsigned_intFromFloat_f64 { + try test_intFromFloat_f64(u256, 0, 0); + try test_intFromFloat_f64(u256, 1 << 0, 0x1p0); + try test_intFromFloat_f64(u256, 1 << 1, 0x1p1); + try test_intFromFloat_f64(u256, 1 << 50, 0x1p50); + try test_intFromFloat_f64(u256, 1 << 100, 0x1p100); + try test_intFromFloat_f64(u256, 1 << 127, 0x1p127); + try test_intFromFloat_f64(u256, 1 << 255, 0x1p255); } -test "fixtfsi" { - try test__fixtfsi(-math.floatMax(f128), math.minInt(i32)); - - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); - - try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); - - try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); - try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); - - try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); - try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); - - try test__fixtfsi(-0x1.000000p+31, -0x80000000); - try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixtfsi(-2.01, -2); - try test__fixtfsi(-2.0, -2); - try test__fixtfsi(-1.99, -1); - try test__fixtfsi(-1.0, -1); - try test__fixtfsi(-0.99, 0); - try test__fixtfsi(-0.5, 0); - try test__fixtfsi(-math.floatMin(f32), 0); - try test__fixtfsi(0.0, 0); - try test__fixtfsi(math.floatMin(f32), 0); - try test__fixtfsi(0.5, 0); - try test__fixtfsi(0.99, 0); - try test__fixtfsi(1.0, 1); - try test__fixtfsi(1.5, 1); - try test__fixtfsi(1.99, 1); - try test__fixtfsi(2.0, 2); - try test__fixtfsi(2.01, 2); - - try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); - try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); - - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); - try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); - - try test__fixtfsi(math.floatMax(f128), math.maxInt(i32)); -} - -test "fixunstfsi" { - try test__fixunstfsi(math.inf(f128), 0xffffffff); - try test__fixunstfsi(0, 0x0); - try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); - try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); - try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); - try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); - try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); - try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); - - try test__fixunstfsi(0x1p+32, 0xFFFFFFFF); -} - -fn test__fixtfdi(a: f128, expected: i64) !void { - const x = __fixtfdi(a); +fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void { + const x = i32_intFromFloat_f128(a); try testing.expect(x == expected); } -fn test__fixunstfdi(a: f128, expected: u64) !void { - const x = __fixunstfdi(a); +fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void { + const x = u32_intFromFloat_f128(a); try testing.expect(x == expected); } -test "fixtfdi" { - try test__fixtfdi(-math.floatMax(f128), math.minInt(i64)); - - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); - - try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); - - try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); - try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); - try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); - - try test__fixtfdi(-0x1.000000p+31, -0x80000000); - try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); - try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); - try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); - - try test__fixtfdi(-2.01, -2); - try test__fixtfdi(-2.0, -2); - try test__fixtfdi(-1.99, -1); - try test__fixtfdi(-1.0, -1); - try test__fixtfdi(-0.99, 0); - try test__fixtfdi(-0.5, 0); - try test__fixtfdi(-math.floatMin(f64), 0); - try test__fixtfdi(0.0, 0); - try test__fixtfdi(math.floatMin(f64), 0); - try test__fixtfdi(0.5, 0); - try test__fixtfdi(0.99, 0); - try test__fixtfdi(1.0, 1); - try test__fixtfdi(1.5, 1); - try test__fixtfdi(1.99, 1); - try test__fixtfdi(2.0, 2); - try test__fixtfdi(2.01, 2); - - try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); - try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); - try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); - try test__fixtfdi(0x1.000000p+31, 0x80000000); - - try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - - try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); - - try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); - - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); - try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); - - try test__fixtfdi(math.floatMax(f128), math.maxInt(i64)); -} - -test "fixunstfdi" { - try test__fixunstfdi(0.0, 0); - - try test__fixunstfdi(0.5, 0); - try test__fixunstfdi(0.99, 0); - try test__fixunstfdi(1.0, 1); - try test__fixunstfdi(1.5, 1); - try test__fixunstfdi(1.99, 1); - try test__fixunstfdi(2.0, 2); - try test__fixunstfdi(2.01, 2); - try test__fixunstfdi(-0.5, 0); - try test__fixunstfdi(-0.99, 0); - try test__fixunstfdi(-1.0, 0); - try test__fixunstfdi(-1.5, 0); - try test__fixunstfdi(-1.99, 0); - try test__fixunstfdi(-2.0, 0); - try test__fixunstfdi(-2.01, 0); - - try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); - try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - - try test__fixunstfdi(-0x1.FFFFFEp+62, 0); - try test__fixunstfdi(-0x1.FFFFFCp+62, 0); - - try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); - - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); - try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); - try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); - try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); - try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF); - - try test__fixunstfdi(-0x1.0000000000000000p+63, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); - try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); -} - -fn test__fixtfti(a: f128, expected: i128) !void { - const x = __fixtfti(a); - try testing.expect(x == expected); +test i32_intFromFloat_f128 { + try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32)); + + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000); + + try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000); + try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i32_intFromFloat_f128(-2.01, -2); + try test_i32_intFromFloat_f128(-2.0, -2); + try test_i32_intFromFloat_f128(-1.99, -1); + try test_i32_intFromFloat_f128(-1.0, -1); + try test_i32_intFromFloat_f128(-0.99, 0); + try test_i32_intFromFloat_f128(-0.5, 0); + try test_i32_intFromFloat_f128(-math.floatMin(f32), 0); + try test_i32_intFromFloat_f128(0.0, 0); + try test_i32_intFromFloat_f128(math.floatMin(f32), 0); + try test_i32_intFromFloat_f128(0.5, 0); + try test_i32_intFromFloat_f128(0.99, 0); + try test_i32_intFromFloat_f128(1.0, 1); + try test_i32_intFromFloat_f128(1.5, 1); + try test_i32_intFromFloat_f128(1.99, 1); + try test_i32_intFromFloat_f128(2.0, 2); + try test_i32_intFromFloat_f128(2.01, 2); + + try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF); + + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); + try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); + + try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32)); } -fn test__fixunstfti(a: f128, expected: u128) !void { - const x = __fixunstfti(a); - try testing.expect(x == expected); +test u32_intFromFloat_f128 { + try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff); + try test_u32_intFromFloat_f128(0, 0x0); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff); + try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff); + try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0); + + try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF); } -test "fixtfti" { - try test__fixtfti(-math.floatMax(f128), math.minInt(i128)); - - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); - - try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); - - try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); - try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); - try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); - try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); - - try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); - try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); +fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void { + const x = i64_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(-2.01, -2); - try test__fixtfti(-2.0, -2); - try test__fixtfti(-1.99, -1); - try test__fixtfti(-1.0, -1); - try test__fixtfti(-0.99, 0); - try test__fixtfti(-0.5, 0); - try test__fixtfti(-math.floatMin(f128), 0); - try test__fixtfti(0.0, 0); - try test__fixtfti(math.floatMin(f128), 0); - try test__fixtfti(0.5, 0); - try test__fixtfti(0.99, 0); - try test__fixtfti(1.0, 1); - try test__fixtfti(1.5, 1); - try test__fixtfti(1.99, 1); - try test__fixtfti(2.0, 2); - try test__fixtfti(2.01, 2); +fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void { + const x = u64_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); - try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); +test i64_intFromFloat_f128 { + try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64)); + + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); + + try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); + + try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); + + try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000); + try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); + try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); + try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); + + try test_i64_intFromFloat_f128(-2.01, -2); + try test_i64_intFromFloat_f128(-2.0, -2); + try test_i64_intFromFloat_f128(-1.99, -1); + try test_i64_intFromFloat_f128(-1.0, -1); + try test_i64_intFromFloat_f128(-0.99, 0); + try test_i64_intFromFloat_f128(-0.5, 0); + try test_i64_intFromFloat_f128(-math.floatMin(f64), 0); + try test_i64_intFromFloat_f128(0.0, 0); + try test_i64_intFromFloat_f128(math.floatMin(f64), 0); + try test_i64_intFromFloat_f128(0.5, 0); + try test_i64_intFromFloat_f128(0.99, 0); + try test_i64_intFromFloat_f128(1.0, 1); + try test_i64_intFromFloat_f128(1.5, 1); + try test_i64_intFromFloat_f128(1.99, 1); + try test_i64_intFromFloat_f128(2.0, 2); + try test_i64_intFromFloat_f128(2.01, 2); + + try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); + try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); + try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); + try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000); + + try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); + + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); + try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); + + try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64)); +} - try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); - try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); - try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); +test u64_intFromFloat_f128 { + try test_u64_intFromFloat_f128(0.0, 0); + + try test_u64_intFromFloat_f128(0.5, 0); + try test_u64_intFromFloat_f128(0.99, 0); + try test_u64_intFromFloat_f128(1.0, 1); + try test_u64_intFromFloat_f128(1.5, 1); + try test_u64_intFromFloat_f128(1.99, 1); + try test_u64_intFromFloat_f128(2.0, 2); + try test_u64_intFromFloat_f128(2.01, 2); + try test_u64_intFromFloat_f128(-0.5, 0); + try test_u64_intFromFloat_f128(-0.99, 0); + try test_u64_intFromFloat_f128(-1.0, 0); + try test_u64_intFromFloat_f128(-1.5, 0); + try test_u64_intFromFloat_f128(-1.99, 0); + try test_u64_intFromFloat_f128(-2.0, 0); + try test_u64_intFromFloat_f128(-2.01, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + + try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0); + + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); + try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001); + try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); + try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); + try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF); + + try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0); + try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0); +} - try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); - try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); +fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void { + const x = i128_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); +fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void { + const x = u128_intFromFloat_f128(a); + try testing.expect(x == expected); +} - try test__fixtfti(math.floatMax(f128), math.maxInt(i128)); +test i128_intFromFloat_f128 { + try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128)); + + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); + + try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); + + try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800); + try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); + + try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000); + try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000); + + try test_i128_intFromFloat_f128(-2.01, -2); + try test_i128_intFromFloat_f128(-2.0, -2); + try test_i128_intFromFloat_f128(-1.99, -1); + try test_i128_intFromFloat_f128(-1.0, -1); + try test_i128_intFromFloat_f128(-0.99, 0); + try test_i128_intFromFloat_f128(-0.5, 0); + try test_i128_intFromFloat_f128(-math.floatMin(f128), 0); + try test_i128_intFromFloat_f128(0.0, 0); + try test_i128_intFromFloat_f128(math.floatMin(f128), 0); + try test_i128_intFromFloat_f128(0.5, 0); + try test_i128_intFromFloat_f128(0.99, 0); + try test_i128_intFromFloat_f128(1.0, 1); + try test_i128_intFromFloat_f128(1.5, 1); + try test_i128_intFromFloat_f128(1.99, 1); + try test_i128_intFromFloat_f128(2.0, 2); + try test_i128_intFromFloat_f128(2.01, 2); + + try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); + try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); + try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000); + try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); + try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); + + try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128)); } -test "fixunstfti" { - try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff); +test u128_intFromFloat_f128 { + try test_u128_intFromFloat_f128(math.inf(f128), 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0.0, 0); + try test_u128_intFromFloat_f128(0.0, 0); - try test__fixunstfti(0.5, 0); - try test__fixunstfti(0.99, 0); - try test__fixunstfti(1.0, 1); - try test__fixunstfti(1.5, 1); - try test__fixunstfti(1.99, 1); - try test__fixunstfti(2.0, 2); - try test__fixunstfti(2.01, 2); - try test__fixunstfti(-0.01, 0); - try test__fixunstfti(-0.99, 0); + try test_u128_intFromFloat_f128(0.5, 0); + try test_u128_intFromFloat_f128(0.99, 0); + try test_u128_intFromFloat_f128(1.0, 1); + try test_u128_intFromFloat_f128(1.5, 1); + try test_u128_intFromFloat_f128(1.99, 1); + try test_u128_intFromFloat_f128(2.0, 2); + try test_u128_intFromFloat_f128(2.01, 2); + try test_u128_intFromFloat_f128(-0.01, 0); + try test_u128_intFromFloat_f128(-0.99, 0); - try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1p+128, 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); - try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); - try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); - try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); + try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); } -fn test__fixunshfti(a: f16, expected: u128) !void { - const x = __fixunshfti(a); +fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void { + const x = impl.u128_intFromFloat_f16(a); try testing.expect(x == expected); } -test "fixunshfti for f16" { - try test__fixunshfti(math.inf(f16), math.maxInt(u128)); - try test__fixunshfti(math.floatMax(f16), 65504); +test u128_intFromFloat_f16 { + try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128)); + try test_u128_intFromFloat_f16(math.floatMax(f16), 65504); } -fn test__fixunsxfti(a: f80, expected: u128) !void { - const x = __fixunsxfti(a); +fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void { + const x = impl.u128_intFromFloat_f80(a); try testing.expect(x == expected); } -test "fixunsxfti for f80" { - try test__fixunsxfti(math.inf(f80), math.maxInt(u128)); - try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128)); - try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64)); +test u128_intFromFloat_f80 { + try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128)); + try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128)); + try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64)); } diff --git a/lib/compiler_rt/limb64.zig b/lib/compiler_rt/limb64.zig index bfe4c441f0525b2e7f5e858e3fa98f81a2e9c865..1d41c0ff1f673c4822b69ccbf0eee69faad19b51 100644 --- a/lib/compiler_rt/limb64.zig +++ b/lib/compiler_rt/limb64.zig @@ -6,7 +6,7 @@ const minInt = std.math.minInt; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const endian = builtin.cpu.arch.endian(); diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index da3757d8224c2ab62e88affd269170b5c64cae6b..9f632f69ff93a9c05663104c5429c7c8e787e761 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -11,7 +11,7 @@ const expectEqual = std.testing.expectEqual; const expectApproxEqRel = std.testing.expectApproxEqRel; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__logh, "__logh"); @@ -25,12 +25,18 @@ comptime { symbol(&logl, "logl"); } -pub fn __logh(a: f16) callconv(.c) f16 { +fn __logh(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(logf(a)); + return @floatCast(log_f32(a)); } -pub fn logf(x_: f32) callconv(.c) f32 { +fn logf(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log_f32(x_: f32) f32 { const ln2_hi: f32 = 6.9313812256e-01; const ln2_lo: f32 = 9.0580006145e-06; const Lg1: f32 = 0xaaaaaa.0p-24; @@ -82,7 +88,10 @@ pub fn logf(x_: f32) callconv(.c) f32 { return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; } -pub fn log(x: f64) callconv(.c) f64 { +fn log(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log_f64(x: f64) f64 { const poly1 = [_]f64{ -0x1p-1, 0x1.5555555555577p-2, @@ -432,11 +441,17 @@ pub fn log(x: f64) callconv(.c) f64 { return @bitCast(y); } -pub fn __logx(a: f80) callconv(.c) f80 { +fn __logx(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(logq(a)); + return @floatCast(log_f128(a)); } +fn logq(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -449,7 +464,7 @@ pub fn __logx(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp -pub fn logq(x: f128) callconv(.c) f128 { +pub fn log_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -626,123 +641,123 @@ pub fn logq(x: f128) callconv(.c) f128 { pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log(x), - 80 => return __logx(x), - 128 => return logq(x), - else => @compileError("unreachable"), + 64 => return log_f64(x), + 80 => return log_f80(x), + 128 => return log_f128(x), + else => comptime unreachable, } } test "logf() special" { - try expectEqual(logf(0.0), -math.inf(f32)); - try expectEqual(logf(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(logf(1.0))); - try expectEqual(logf(math.e), 1.0); - try expectEqual(logf(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(logf(-1.0))); - try expect(math.isNan(logf(-math.inf(f32)))); - try expect(math.isNan(logf(math.nan(f32)))); - try expect(math.isNan(logf(math.snan(f32)))); + try expectEqual(log_f32(0.0), -math.inf(f32)); + try expectEqual(log_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log_f32(1.0))); + try expectEqual(log_f32(math.e), 1.0); + try expectEqual(log_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log_f32(-1.0))); + try expect(math.isNan(log_f32(-math.inf(f32)))); + try expect(math.isNan(log_f32(math.nan(f32)))); + try expect(math.isNan(log_f32(math.snan(f32)))); } test "logf() sanity" { - try expect(math.isNan(logf(-0x1.0223a0p+3))); - try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0); - try expect(math.isNan(logf(-0x1.0c34b4p+3))); - try expect(math.isNan(logf(-0x1.a206f0p+2))); - try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1); - try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2); - try expect(math.isNan(logf(-0x1.a05cc8p-2))); - try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1); - try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2); - try expect(math.isNan(logf(-0x1.5b86eap-1))); + try expect(math.isNan(log_f32(-0x1.0223a0p+3))); + try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0); + try expect(math.isNan(log_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log_f32(-0x1.a206f0p+2))); + try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1); + try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2); + try expect(math.isNan(log_f32(-0x1.a05cc8p-2))); + try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1); + try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2); + try expect(math.isNan(log_f32(-0x1.5b86eap-1))); } test "logf() boundary" { - try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value - try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value - try expect(math.isNan(logf(-0x1p-149))); // Min negative input value - try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 - try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 - try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal - try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal + try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value + try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value + try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value + try expectEqual(log_f32(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 + try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 + try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal + try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal } test "log() special" { - try expectEqual(log(0.0), -math.inf(f64)); - try expectEqual(log(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log(1.0))); - try expectEqual(log(math.e), 1.0); - try expectEqual(log(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log(-1.0))); - try expect(math.isNan(log(-math.inf(f64)))); - try expect(math.isNan(log(math.nan(f64)))); - try expect(math.isNan(log(math.snan(f64)))); + try expectEqual(log_f64(0.0), -math.inf(f64)); + try expectEqual(log_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log_f64(1.0))); + try expectEqual(log_f64(math.e), 1.0); + try expectEqual(log_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log_f64(-1.0))); + try expect(math.isNan(log_f64(-math.inf(f64)))); + try expect(math.isNan(log_f64(math.nan(f64)))); + try expect(math.isNan(log_f64(math.snan(f64)))); } test "log() sanity" { - try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); - try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); - try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); - try expect(math.isNan(log(-0x1.a05cc754481d1p-2))); - try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); - try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); - try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); + try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); + try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); + try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); + try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); + try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1))); } test "log() boundary" { - try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value - try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value - try expect(math.isNan(log(-0x1p-1074))); // Min negative input value - try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 - try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 - try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal - try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal + try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value + try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value + try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log_f64(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 + try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 + try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal + try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal } test "logq() special" { - try expectEqual(logq(0.0), -math.inf(f128)); - try expectEqual(logq(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(logq(1.0))); + try expectEqual(log_f128(0.0), -math.inf(f128)); + try expectEqual(log_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log_f128(1.0))); // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999 - // is the correctly rounded value of logq(math.e) - try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0)); - try expectEqual(logq(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(logq(-1.0))); - try expect(math.isNan(logq(-math.inf(f128)))); - try expect(math.isNan(logq(math.nan(f128)))); - try expect(math.isNan(logq(math.snan(f128)))); + // is the correctly rounded value of log_f128(math.e) + try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0)); + try expectEqual(log_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log_f128(-1.0))); + try expect(math.isNan(log_f128(-math.inf(f128)))); + try expect(math.isNan(log_f128(math.nan(f128)))); + try expect(math.isNan(log_f128(math.snan(f128)))); } test "logq() boundary" { - try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value - try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value - try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value - try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 - try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 - try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal - try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal + try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value + try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value + try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log_f128(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 + try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 + try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal + try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal } test "logq() sanity" { - try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); - try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); - try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); - try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); - try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); - try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); - try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); - try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); - try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); - try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); - try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); + try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); + try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); + try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); + try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); + try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); + try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); + try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); + try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); + try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); + try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); + try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); // testing near 1 - try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); - try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); - try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); - try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); - try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); + try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); + try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); + try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); + try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); + try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); } diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index 18479d534a347721c842b682228f29688213909c..6a554e0ea79ff597dfdeeea31477e1c6ebfbac1c 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -25,12 +25,18 @@ comptime { symbol(&log10l, "log10l"); } -pub fn __log10h(a: f16) callconv(.c) f16 { +fn __log10h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log10_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log10_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(log10f(a)); + return @floatCast(log10_f32(a)); } -pub fn log10f(x_: f32) callconv(.c) f32 { +fn log10f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log10_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log10_f32(x_: f32) f32 { const ivln10hi: f32 = 4.3432617188e-01; const ivln10lo: f32 = -3.1689971365e-05; const log10_2hi: f32 = 3.0102920532e-01; @@ -90,7 +96,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 { return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi; } -pub fn log10(x_: f64) callconv(.c) f64 { +fn log10(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log10_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log10_f64(x_: f64) f64 { const ivln10hi: f64 = 4.34294481878168880939e-01; const ivln10lo: f64 = 2.50829467116452752298e-11; const log10_2hi: f64 = 3.01029995663611771306e-01; @@ -165,11 +174,17 @@ pub fn log10(x_: f64) callconv(.c) f64 { return val_lo + val_hi; } -pub fn __log10x(a: f80) callconv(.c) f80 { +fn __log10x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log10_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log10_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(log10q(a)); + return @floatCast(log10_f128(a)); } +fn log10q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log10_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -182,7 +197,7 @@ pub fn __log10x(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp -pub fn log10q(x: f128) callconv(.c) f128 { +pub fn log10_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -359,124 +374,124 @@ pub fn log10q(x: f128) callconv(.c) f128 { pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log10(x), - 80 => return __log10x(x), - 128 => return log10q(x), - else => @compileError("unreachable"), + 64 => return log10_f64(x), + 80 => return log10_f80(x), + 128 => return log10_f128(x), + else => comptime unreachable, } } test "log10f() special" { - try expectEqual(log10f(0.0), -math.inf(f32)); - try expectEqual(log10f(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(log10f(1.0))); - try expectEqual(log10f(10.0), 1.0); - try expectEqual(log10f(0.1), -1.0); - try expectEqual(log10f(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(log10f(-1.0))); - try expect(math.isNan(log10f(-math.inf(f32)))); - try expect(math.isNan(log10f(math.nan(f32)))); - try expect(math.isNan(log10f(math.snan(f32)))); + try expectEqual(log10_f32(0.0), -math.inf(f32)); + try expectEqual(log10_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log10_f32(1.0))); + try expectEqual(log10_f32(10.0), 1.0); + try expectEqual(log10_f32(0.1), -1.0); + try expectEqual(log10_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log10_f32(-1.0))); + try expect(math.isNan(log10_f32(-math.inf(f32)))); + try expect(math.isNan(log10_f32(math.nan(f32)))); + try expect(math.isNan(log10_f32(math.snan(f32)))); } test "log10f() sanity" { - try expect(math.isNan(log10f(-0x1.0223a0p+3))); - try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1); - try expect(math.isNan(log10f(-0x1.0c34b4p+3))); - try expect(math.isNan(log10f(-0x1.a206f0p+2))); - try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1); - try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit - try expect(math.isNan(log10f(-0x1.a05cc8p-2))); - try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2); - try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4); - try expect(math.isNan(log10f(-0x1.5b86eap-1))); + try expect(math.isNan(log10_f32(-0x1.0223a0p+3))); + try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1); + try expect(math.isNan(log10_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log10_f32(-0x1.a206f0p+2))); + try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1); + try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit + try expect(math.isNan(log10_f32(-0x1.a05cc8p-2))); + try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2); + try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4); + try expect(math.isNan(log10_f32(-0x1.5b86eap-1))); } test "log10f() boundary" { - try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value - try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value - try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value - try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 - try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 - try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal - try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal + try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value + try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value + try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value + try expectEqual(log10_f32(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 + try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 + try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal + try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal } test "log10() special" { - try expectEqual(log10(0.0), -math.inf(f64)); - try expectEqual(log10(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log10(1.0))); - try expectEqual(log10(10.0), 1.0); - try expectEqual(log10(0.1), -1.0); - try expectEqual(log10(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log10(-1.0))); - try expect(math.isNan(log10(-math.inf(f64)))); - try expect(math.isNan(log10(math.nan(f64)))); - try expect(math.isNan(log10(math.snan(f64)))); + try expectEqual(log10_f64(0.0), -math.inf(f64)); + try expectEqual(log10_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log10_f64(1.0))); + try expectEqual(log10_f64(10.0), 1.0); + try expectEqual(log10_f64(0.1), -1.0); + try expectEqual(log10_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log10_f64(-1.0))); + try expect(math.isNan(log10_f64(-math.inf(f64)))); + try expect(math.isNan(log10_f64(math.nan(f64)))); + try expect(math.isNan(log10_f64(math.snan(f64)))); } test "log10() sanity" { - try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); - try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); - try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); - try expect(math.isNan(log10(-0x1.a05cc754481d1p-2))); - try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); - try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); - try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); + try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); + try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); + try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); + try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); + try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1))); } test "log10() boundary" { - try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value - try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value - try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value - try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 - try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 - try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal - try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal + try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value + try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value + try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log10_f64(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 + try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 + try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal + try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal } test "log10q() special" { - try expectEqual(log10q(0.0), -math.inf(f128)); - try expectEqual(log10q(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(log10q(1.0))); - try expectEqual(log10q(10.0), 1.0); - try expectEqual(log10q(0.1), -1.0); - try expectEqual(log10q(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(log10q(-1.0))); - try expect(math.isNan(log10q(-math.inf(f128)))); - try expect(math.isNan(log10q(math.nan(f128)))); - try expect(math.isNan(log10q(math.snan(f128)))); + try expectEqual(log10_f128(0.0), -math.inf(f128)); + try expectEqual(log10_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log10_f128(1.0))); + try expectEqual(log10_f128(10.0), 1.0); + try expectEqual(log10_f128(0.1), -1.0); + try expectEqual(log10_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log10_f128(-1.0))); + try expect(math.isNan(log10_f128(-math.inf(f128)))); + try expect(math.isNan(log10_f128(math.nan(f128)))); + try expect(math.isNan(log10_f128(math.snan(f128)))); } test "log10q() sanity" { - try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); - try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); - try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); - try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); - try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); - try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); - try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); - try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); - try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); - try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); + try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); + try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); + try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); + try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); + try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); + try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); + try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); + try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); + try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); + try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); // testing near 1 - try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); - try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); - try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); - try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); - try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); - try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); + try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); + try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); + try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); + try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); + try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); + try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); } test "log10q() boundary" { - try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value - try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value - try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value - try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 - try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 - try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal - try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal + try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value + try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value + try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log10_f128(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 + try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 + try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal + try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal } diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index 8db17aaf3f26f257482af43b7bc125d4747dbfe2..b748a0af826586065f1f5369a6f1c61492b4cf99 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -26,12 +26,18 @@ comptime { symbol(&log2l, "log2l"); } -pub fn __log2h(a: f16) callconv(.c) f16 { +fn __log2h(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(log2_f16(compiler_rt.f16.fromAbi(a))); +} +pub fn log2_f16(a: f16) f16 { // TODO: more efficient implementation - return @floatCast(log2f(a)); + return @floatCast(log2_f32(a)); } -pub fn log2f(x_: f32) callconv(.c) f32 { +fn log2f(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(log2_f32(compiler_rt.f32.fromAbi(a))); +} +pub fn log2_f32(x_: f32) f32 { const ivln2hi: f32 = 1.4428710938e+00; const ivln2lo: f32 = -1.7605285393e-04; const Lg1: f32 = 0xaaaaaa.0p-24; @@ -87,7 +93,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 { return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k)); } -pub fn log2(x_: f64) callconv(.c) f64 { +fn log2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(log2_f64(compiler_rt.f64.fromAbi(a))); +} +pub fn log2_f64(x_: f64) f64 { const ivln2hi: f64 = 1.44269504072144627571e+00; const ivln2lo: f64 = 1.67517131648865118353e-10; const Lg1: f64 = 6.666666666666735130e-01; @@ -158,11 +167,17 @@ pub fn log2(x_: f64) callconv(.c) f64 { return val_lo + val_hi; } -pub fn __log2x(a: f80) callconv(.c) f80 { +fn __log2x(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(log2_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn log2_f80(a: f80) f80 { // TODO: more efficient implementation - return @floatCast(log2q(a)); + return @floatCast(log2_f128(a)); } +fn log2q(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(log2_f128(compiler_rt.f128.fromAbi(a))); +} /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" /// by PTP Tang in ACM Transactions on Mathematical Software (TOMS), 1990 /// @@ -175,7 +190,7 @@ pub fn __log2x(a: f80) callconv(.c) f80 { /// /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): /// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp -pub fn log2q(x: f128) callconv(.c) f128 { +pub fn log2_f128(x: f128) f128 { const impl = @import("log_f128.zig"); if (impl.specialCases(x)) |y| @@ -351,117 +366,117 @@ pub fn log2q(x: f128) callconv(.c) f128 { pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return log2(x), - 80 => return __log2x(x), - 128 => return log2q(x), - else => @compileError("unreachable"), + 64 => return log2_f64(x), + 80 => return log2_f80(x), + 128 => return log2_f128(x), + else => comptime unreachable, } } test "log2f() special" { - try expectEqual(log2f(0.0), -math.inf(f32)); - try expectEqual(log2f(-0.0), -math.inf(f32)); - try expect(math.isPositiveZero(log2f(1.0))); - try expectEqual(log2f(2.0), 1.0); - try expectEqual(log2f(math.inf(f32)), math.inf(f32)); - try expect(math.isNan(log2f(-1.0))); - try expect(math.isNan(log2f(-math.inf(f32)))); - try expect(math.isNan(log2f(math.nan(f32)))); - try expect(math.isNan(log2f(math.snan(f32)))); + try expectEqual(log2_f32(0.0), -math.inf(f32)); + try expectEqual(log2_f32(-0.0), -math.inf(f32)); + try expect(math.isPositiveZero(log2_f32(1.0))); + try expectEqual(log2_f32(2.0), 1.0); + try expectEqual(log2_f32(math.inf(f32)), math.inf(f32)); + try expect(math.isNan(log2_f32(-1.0))); + try expect(math.isNan(log2_f32(-math.inf(f32)))); + try expect(math.isNan(log2_f32(math.nan(f32)))); + try expect(math.isNan(log2_f32(math.snan(f32)))); } test "log2f() sanity" { - try expect(math.isNan(log2f(-0x1.0223a0p+3))); - try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1); - try expect(math.isNan(log2f(-0x1.0c34b4p+3))); - try expect(math.isNan(log2f(-0x1.a206f0p+2))); - try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1); - try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit - try expect(math.isNan(log2f(-0x1.a05cc8p-2))); - try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1); - try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2); - try expect(math.isNan(log2f(-0x1.5b86eap-1))); + try expect(math.isNan(log2_f32(-0x1.0223a0p+3))); + try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1); + try expect(math.isNan(log2_f32(-0x1.0c34b4p+3))); + try expect(math.isNan(log2_f32(-0x1.a206f0p+2))); + try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1); + try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit + try expect(math.isNan(log2_f32(-0x1.a05cc8p-2))); + try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1); + try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2); + try expect(math.isNan(log2_f32(-0x1.5b86eap-1))); } test "log2f() boundary" { - try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value - try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value - try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value - try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 - try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 - try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal - try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal + try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value + try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value + try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value + try expectEqual(log2_f32(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 + try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 + try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal + try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal } test "log2() special" { - try expectEqual(log2(0.0), -math.inf(f64)); - try expectEqual(log2(-0.0), -math.inf(f64)); - try expect(math.isPositiveZero(log2(1.0))); - try expectEqual(log2(2.0), 1.0); - try expectEqual(log2(math.inf(f64)), math.inf(f64)); - try expect(math.isNan(log2(-1.0))); - try expect(math.isNan(log2(-math.inf(f64)))); - try expect(math.isNan(log2(math.nan(f64)))); - try expect(math.isNan(log2(math.snan(f64)))); + try expectEqual(log2_f64(0.0), -math.inf(f64)); + try expectEqual(log2_f64(-0.0), -math.inf(f64)); + try expect(math.isPositiveZero(log2_f64(1.0))); + try expectEqual(log2_f64(2.0), 1.0); + try expectEqual(log2_f64(math.inf(f64)), math.inf(f64)); + try expect(math.isNan(log2_f64(-1.0))); + try expect(math.isNan(log2_f64(-math.inf(f64)))); + try expect(math.isNan(log2_f64(math.nan(f64)))); + try expect(math.isNan(log2_f64(math.snan(f64)))); } test "log2() sanity" { - try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3))); - try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); - try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3))); - try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2))); - try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); - try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); - try expect(math.isNan(log2(-0x1.a05cc754481d1p-2))); - try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); - try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); - try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1))); + try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3))); + try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); + try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3))); + try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2))); + try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); + try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); + try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2))); + try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); + try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); + try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1))); } test "log2() boundary" { - try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value - try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value - try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value - try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 - try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 - try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal - try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal + try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value + try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value + try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value + try expectEqual(log2_f64(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 + try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 + try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal + try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal } test "log2q() special" { - try expectEqual(log2q(0.0), -math.inf(f128)); - try expectEqual(log2q(-0.0), -math.inf(f128)); - try expect(math.isPositiveZero(log2q(1.0))); - try expectEqual(log2q(2.0), 1.0); - try expectEqual(log2q(math.inf(f128)), math.inf(f128)); - try expect(math.isNan(log2q(-1.0))); - try expect(math.isNan(log2q(-math.inf(f128)))); - try expect(math.isNan(log2q(math.nan(f128)))); - try expect(math.isNan(log2q(math.snan(f128)))); + try expectEqual(log2_f128(0.0), -math.inf(f128)); + try expectEqual(log2_f128(-0.0), -math.inf(f128)); + try expect(math.isPositiveZero(log2_f128(1.0))); + try expectEqual(log2_f128(2.0), 1.0); + try expectEqual(log2_f128(math.inf(f128)), math.inf(f128)); + try expect(math.isNan(log2_f128(-1.0))); + try expect(math.isNan(log2_f128(-math.inf(f128)))); + try expect(math.isNan(log2_f128(math.nan(f128)))); + try expect(math.isNan(log2_f128(math.snan(f128)))); } test "log2q() boundary" { - try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value - try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value - try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value - try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 - try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 - try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal - try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal + try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value + try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value + try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value + try expectEqual(log2_f128(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 + try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 + try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal + try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal } test "log2q() sanity" { - try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); - try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1); - try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); - try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); - try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); - try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); + try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); + try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1); + try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); + try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); + try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); + try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); // test near 1 - try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); - try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); - try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); - try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); - try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); + try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); + try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); + try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); + try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); + try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); } diff --git a/lib/compiler_rt/mulc3.zig b/lib/compiler_rt/mulc3.zig index eea753245f7687b2e3e9b65c12bdd278f1a3c757..fc0f2d24b4f603d9c933eb1328dbf5b73e4f41bc 100644 --- a/lib/compiler_rt/mulc3.zig +++ b/lib/compiler_rt/mulc3.zig @@ -3,19 +3,80 @@ const isNan = std.math.isNan; const isInf = std.math.isInf; const copysign = std.math.copysign; -pub fn Complex(comptime T: type) type { - return extern struct { - real: T, - imag: T, - }; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; +const Complex = compiler_rt.Complex; + +comptime { + if (@import("builtin").zig_backend != .stage2_c) { + symbol(&__mulhc3, "__mulhc3"); + symbol(&__mulsc3, "__mulsc3"); + symbol(&__muldc3, "__muldc3"); + symbol(&__mulxc3, "__mulxc3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__multc3, "__mulkc3"); + } else { + symbol(&__multc3, "__multc3"); + } + } +} + +fn __mulhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { + return compiler_rt.f16.complex.toAbi(mul_cf16( + compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { + return mulc3(f16, a, b); +} + +fn __mulsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { + return compiler_rt.f32.complex.toAbi(mul_cf32( + compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { + return mulc3(f32, a, b); +} + +fn __muldc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { + return compiler_rt.f64.complex.toAbi(mul_cf64( + compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { + return mulc3(f64, a, b); +} + +fn __mulxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { + return compiler_rt.f80.complex.toAbi(mul_cf80( + compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { + return mulc3(f80, a, b); +} + +fn __multc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { + return compiler_rt.f128.complex.toAbi(mul_cf128( + compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), + compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), + )); +} +pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { + return mulc3(f128, a, b); } /// Implementation based on Annex G of C17 Standard (N2176) -pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Complex(T) { - var a = a_in; - var b = b_in; - var c = c_in; - var d = d_in; +inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { + var a = lhs.real; + var b = lhs.imag; + var c = rhs.real; + var d = rhs.imag; const ac = a * c; const bd = b * d; @@ -77,3 +138,7 @@ pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Comple } return z; } + +test { + _ = @import("mulc3_test.zig"); +} diff --git a/lib/compiler_rt/mulc3_test.zig b/lib/compiler_rt/mulc3_test.zig index 3872cb34a6f9198dce4b482be03de720dce17696..748a3bc120ad6cfa3f82b2226f537a6bc63771b6 100644 --- a/lib/compiler_rt/mulc3_test.zig +++ b/lib/compiler_rt/mulc3_test.zig @@ -2,64 +2,45 @@ const std = @import("std"); const math = std.math; const expect = std.testing.expect; -const Complex = @import("./mulc3.zig").Complex; -const __mulhc3 = @import("./mulhc3.zig").__mulhc3; -const __mulsc3 = @import("./mulsc3.zig").__mulsc3; -const __muldc3 = @import("./muldc3.zig").__muldc3; -const __mulxc3 = @import("./mulxc3.zig").__mulxc3; -const __multc3 = @import("./multc3.zig").__multc3; +const Complex = @import("../compiler_rt.zig").Complex; +const impl = @import("mulc3.zig"); +const mul_cf16 = impl.mul_cf16; +const mul_cf32 = impl.mul_cf32; +const mul_cf64 = impl.mul_cf64; +const mul_cf80 = impl.mul_cf80; +const mul_cf128 = impl.mul_cf128; test "mulc3" { - try testMul(f16, __mulhc3); - try testMul(f32, __mulsc3); - try testMul(f64, __muldc3); - try testMul(f80, __mulxc3); - try testMul(f128, __multc3); + try testMul(f16, mul_cf16); + try testMul(f32, mul_cf32); + try testMul(f64, mul_cf64); + try testMul(f80, mul_cf80); + try testMul(f128, mul_cf128); } -fn testMul(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { +fn testMul(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); try expect(result.real == -1.0); - try expect(result.imag == 0.0); + try expect(math.isPositiveZero(result.imag)); } { - const a: T = 1.0; - const b: T = 0.0; - const c: T = -4.0; - const d: T = 0.0; - - const result = f(a, b, c, d); + const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); try expect(result.real == -4.0); - try expect(result.imag == 0.0); + try expect(math.isPositiveZero(result.imag)); } { // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, // then the result of the * operator is an infinity; - const a: T = math.inf(T); - const b: T = -math.inf(T); - const c: T = 1.0; - const d: T = 0.0; - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == -math.inf(T)); + const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isNegativeInf(result.imag)); } { // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, // then the result of the * operator is an infinity; - const a: T = math.inf(T); - const b: T = -1.0; - const c: T = 1.0; - const d: T = math.inf(T); - - const result = f(a, b, c, d); - try expect(result.real == math.inf(T)); - try expect(result.imag == math.inf(T)); + const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) }); + try expect(math.isPositiveInf(result.real)); + try expect(math.isPositiveInf(result.imag)); } } diff --git a/lib/compiler_rt/muldc3.zig b/lib/compiler_rt/muldc3.zig deleted file mode 100644 index d5facaa2b645670b6bf6e0953ec6b73342342329..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/muldc3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const mulc3 = @import("./mulc3.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__muldc3, "__muldc3"); - } -} - -pub fn __muldc3(a: f64, b: f64, c: f64, d: f64) callconv(.c) mulc3.Complex(f64) { - return mulc3.mulc3(f64, a, b, c, d); -} diff --git a/lib/compiler_rt/muldf3.zig b/lib/compiler_rt/muldf3.zig deleted file mode 100644 index b8809e76da8d11e04c181d9dea86911aaac1cb29..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/muldf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dmul, "__aeabi_dmul"); - } else { - symbol(&__muldf3, "__muldf3"); - } -} - -pub fn __muldf3(a: f64, b: f64) callconv(.c) f64 { - return mulf3(f64, a, b); -} - -fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return mulf3(f64, a, b); -} diff --git a/lib/compiler_rt/mulf3.zig b/lib/compiler_rt/mulf3.zig index d6b5a4719068cf2e27345f73e5f29994fc72e6d3..7367339dbc82f74dc99a9f6de7f842e8cbb71968 100644 --- a/lib/compiler_rt/mulf3.zig +++ b/lib/compiler_rt/mulf3.zig @@ -2,10 +2,76 @@ const std = @import("std"); const math = std.math; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + symbol(&__mulhf3, "__mulhf3"); + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_fmul, "__aeabi_fmul"); + symbol(&__aeabi_dmul, "__aeabi_dmul"); + } else { + symbol(&__mulsf3, "__mulsf3"); + symbol(&__muldf3, "__muldf3"); + } + symbol(&__mulxf3, "__mulxf3"); + if (compiler_rt.want_ppc_abi) { + symbol(&__multf3, "__mulkf3"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_mul, "_Qp_mul"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__multf3, "_Q_mul"); + } else { + symbol(&__multf3, "__multf3"); + } +} + +fn __mulhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(mul_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); +} +pub fn mul_f16(a: f16, b: f16) f16 { + return mulf3(f16, a, b); +} + +fn __mulsf3(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(mul_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); +} +fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { + return mul_f32(a, b); +} +pub fn mul_f32(a: f32, b: f32) f32 { + return mulf3(f32, a, b); +} + +fn __muldf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(mul_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); +} +fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { + return mul_f64(a, b); +} +pub fn mul_f64(a: f64, b: f64) f64 { + return mulf3(f64, a, b); +} + +fn __mulxf3(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(mul_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b))); +} +pub fn mul_f80(a: f80, b: f80) f80 { + return mulf3(f80, a, b); +} + +fn __multf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(mul_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); +} +fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { + c.* = mul_f128(a.*, b.*); +} +pub fn mul_f128(a: f128, b: f128) f128 { + return mulf3(f128, a, b); +} /// Ported from: /// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc -pub inline fn mulf3(comptime T: type, a: T, b: T) T { +inline fn mulf3(comptime T: type, a: T, b: T) T { @setRuntimeSafety(compiler_rt.test_safety); const typeWidth = @typeInfo(T).float.bits; const significandBits = math.floatMantissaBits(T); diff --git a/lib/compiler_rt/mulf3_test.zig b/lib/compiler_rt/mulf3_test.zig index 751b8933f65bc20e4b630c125fa60f42d5e27529..a2595e21a6d1ca5dd44f1ce67e6dfb6b4ee4cd9f 100644 --- a/lib/compiler_rt/mulf3_test.zig +++ b/lib/compiler_rt/mulf3_test.zig @@ -7,10 +7,12 @@ const math = std.math; const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64); -const __multf3 = @import("multf3.zig").__multf3; -const __mulxf3 = @import("mulxf3.zig").__mulxf3; -const __muldf3 = @import("muldf3.zig").__muldf3; -const __mulsf3 = @import("mulsf3.zig").__mulsf3; +const impl = @import("mulf3.zig"); +const mul_f16 = impl.mul_f16; +const mul_f32 = impl.mul_f32; +const mul_f64 = impl.mul_f64; +const mul_f80 = impl.mul_f80; +const mul_f128 = impl.mul_f128; // return true if equal // use two 64-bit integers instead of one 128-bit integer @@ -34,8 +36,8 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { return false; } -fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { - const x = __multf3(a, b); +fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { + const x = mul_f128(a, b); if (compareResultLD(x, expected_hi, expected_lo)) return; @@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 { } test "multf3" { // qNaN * any = qNaN - try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + try test_mul_f128(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // NaN * any = NaN const a = makeNaN128(0x800030000000); - try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + try test_mul_f128(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // inf * any = inf - try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); + try test_mul_f128(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); // any * any - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))), @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))), 0x400423e7f9e3c9fc, 0xd906c2c2a85777c4, ); - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))), @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))), 0x3fc52a163c6223fc, 0xc94c4bf0430768b4, ); - try test__multf3( + try test_mul_f128( 0x1.234425696abcad34a35eeffefdcbap+456, 0x451.ed98d76e5d46e5f24323dff21ffp+600, 0x44293a91de5e0e94, 0xe8ed17cc2cdf64ac, ); - try test__multf3( + try test_mul_f128( @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))), @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))), 0x3d4f37c1a3137cae, 0xfc6807048bc2836a, ); - try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); + try test_mul_f128(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); // Denormal operands. - try test__multf3( + try test_mul_f128( 0x0.0000000000000000000000000001p-16382, 0x1p16383, 0x3f90000000000000, 0x0, ); - try test__multf3( + try test_mul_f128( 0x1p16383, 0x0.0000000000000000000000000001p-16382, 0x3f90000000000000, 0x0, ); - try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); - try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); - try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); + try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); + try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); + try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); } const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); -fn test__mulxf3(a: f80, b: f80, expected: u80) !void { - const x = __mulxf3(a, b); +fn test_mul_f80(a: f80, b: f80, expected: u80) !void { + const x = mul_f80(a, b); const rep: u80 = @bitCast(x); if (rep == expected) @@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void { test "mulxf3" { // NaN * any = NaN - try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); - try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); + try test_mul_f80(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); + try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); // any * NaN = NaN - try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); - try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); + try test_mul_f80(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); + try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); // NaN * inf = NaN - try test__mulxf3(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80))); + try test_mul_f80(qnan80, math.inf(f80), @as(u80, @bitCast(qnan80))); // inf * NaN = NaN - try test__mulxf3(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80))); + try test_mul_f80(math.inf(f80), qnan80, @as(u80, @bitCast(qnan80))); // inf * inf = inf - try test__mulxf3(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(math.inf(f80), math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); // inf * -inf = -inf - try test__mulxf3(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); + try test_mul_f80(math.inf(f80), -math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); // -inf + inf = -inf - try test__mulxf3(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); + try test_mul_f80(-math.inf(f80), math.inf(f80), @as(u80, @bitCast(-math.inf(f80)))); // inf * any = inf - try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @as(u80, @bitCast(math.inf(f80)))); // any * inf = inf - try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); + try test_mul_f80(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @as(u80, @bitCast(math.inf(f80)))); // any * any - try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); - try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact + try test_mul_f80(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); + try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up - try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up + try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact - try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even - try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up - try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal - try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal - try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal + try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even + try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up + try test_mul_f80(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal + try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal + try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal } diff --git a/lib/compiler_rt/mulhc3.zig b/lib/compiler_rt/mulhc3.zig deleted file mode 100644 index 4e0d3f875389ddf2f02bb7ddb3f75106e6d48513..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulhc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulhc3, "__mulhc3"); - } -} - -pub fn __mulhc3(a: f16, b: f16, c: f16, d: f16) callconv(.c) mulc3.Complex(f16) { - return mulc3.mulc3(f16, a, b, c, d); -} diff --git a/lib/compiler_rt/mulhf3.zig b/lib/compiler_rt/mulhf3.zig deleted file mode 100644 index 46ce7a6b999005704db84280e3e83c7be05985b6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulhf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - symbol(&__mulhf3, "__mulhf3"); -} - -pub fn __mulhf3(a: f16, b: f16) callconv(.c) f16 { - return mulf3(f16, a, b); -} diff --git a/lib/compiler_rt/mulsc3.zig b/lib/compiler_rt/mulsc3.zig deleted file mode 100644 index e735e65eade6a77f908abe8b4b25e8fc30af7f9f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulsc3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulsc3, "__mulsc3"); - } -} - -pub fn __mulsc3(a: f32, b: f32, c: f32, d: f32) callconv(.c) mulc3.Complex(f32) { - return mulc3.mulc3(f32, a, b, c, d); -} diff --git a/lib/compiler_rt/mulsf3.zig b/lib/compiler_rt/mulsf3.zig deleted file mode 100644 index 81f9eafae213d8cba10579b86f109bdfd361ba41..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulsf3.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fmul, "__aeabi_fmul"); - } else { - symbol(&__mulsf3, "__mulsf3"); - } -} - -pub fn __mulsf3(a: f32, b: f32) callconv(.c) f32 { - return mulf3(f32, a, b); -} - -fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return mulf3(f32, a, b); -} diff --git a/lib/compiler_rt/multc3.zig b/lib/compiler_rt/multc3.zig deleted file mode 100644 index 4914735b10f63ec38d3487738e461769db6f8669..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/multc3.zig +++ /dev/null @@ -1,15 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - if (compiler_rt.want_ppc_abi) - symbol(&__multc3, "__mulkc3"); - symbol(&__multc3, "__multc3"); - } -} - -pub fn __multc3(a: f128, b: f128, c: f128, d: f128) callconv(.c) mulc3.Complex(f128) { - return mulc3.mulc3(f128, a, b, c, d); -} diff --git a/lib/compiler_rt/multf3.zig b/lib/compiler_rt/multf3.zig deleted file mode 100644 index 7d10c70777176e7a8580eb3b909546e42535785e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/multf3.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__multf3, "__mulkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_mul, "_Qp_mul"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__multf3, "_Q_mul"); - } - symbol(&__multf3, "__multf3"); -} - -pub fn __multf3(a: f128, b: f128) callconv(.c) f128 { - return mulf3(f128, a, b); -} - -fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = mulf3(f128, a.*, b.*); -} diff --git a/lib/compiler_rt/mulvsi3.zig b/lib/compiler_rt/mulvsi3.zig index 0935ea497afa52a46f515c83c40c2d8cc5bc02db..f2456fa7cb825a36a359d667d26e5f06eb2c95e4 100644 --- a/lib/compiler_rt/mulvsi3.zig +++ b/lib/compiler_rt/mulvsi3.zig @@ -1,7 +1,8 @@ const testing = @import("std").testing; const mulv = @import("mulo.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__mulvsi3, "__mulvsi3"); @@ -10,7 +11,7 @@ comptime { pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 { var overflow: c_int = 0; const sum = mulv.__mulosi4(a, b, &overflow); - if (overflow != 0) @panic("compiler-rt: integer overflow"); + if (overflow != 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/mulxc3.zig b/lib/compiler_rt/mulxc3.zig deleted file mode 100644 index ac0e189f63ba4d4ce2f0a753c4f7409e0b551d23..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulxc3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulc3 = @import("./mulc3.zig"); - -comptime { - if (@import("builtin").zig_backend != .stage2_c) { - symbol(&__mulxc3, "__mulxc3"); - } -} - -pub fn __mulxc3(a: f80, b: f80, c: f80, d: f80) callconv(.c) mulc3.Complex(f80) { - return mulc3.mulc3(f80, a, b, c, d); -} diff --git a/lib/compiler_rt/mulxf3.zig b/lib/compiler_rt/mulxf3.zig deleted file mode 100644 index dcf783a4a6bc434275416e9da0079f65b3354277..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/mulxf3.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const mulf3 = @import("./mulf3.zig").mulf3; - -comptime { - symbol(&__mulxf3, "__mulxf3"); -} - -pub fn __mulxf3(a: f80, b: f80) callconv(.c) f80 { - return mulf3(f80, a, b); -} diff --git a/lib/compiler_rt/negv.zig b/lib/compiler_rt/negv.zig index 7c67a51c34ab72f9c3f0038024e45ca79413d955..c6d61611f1b24d3697dcdc4201f5ff2d8c1cf40c 100644 --- a/lib/compiler_rt/negv.zig +++ b/lib/compiler_rt/negv.zig @@ -33,8 +33,7 @@ inline fn negvXi(comptime ST: type, a: ST) ST { }; const N: UT = @bitSizeOf(ST); const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1)))); - if (a == min) - @panic("compiler_rt negv: overflow"); + if (a == min) @panic("integer overflow"); return -a; } diff --git a/lib/compiler_rt/os_version_check.zig b/lib/compiler_rt/os_version_check.zig index e575fef9ce553fee90cc9f7cc900689c5804cb20..96724a14e8092aae7693e4ab869ab3282a9ea762 100644 --- a/lib/compiler_rt/os_version_check.zig +++ b/lib/compiler_rt/os_version_check.zig @@ -3,7 +3,6 @@ const testing = std.testing; const builtin = @import("builtin"); const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; -const panic = @import("../compiler_rt.zig").panic; const have_availability_version_check = builtin.os.tag.isDarwin() and builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte); diff --git a/lib/compiler_rt/parity.zig b/lib/compiler_rt/parity.zig index e3881699042fafc3fc0da7415e6fb2bb6d1aedde..9540cf49f629556b73f77067ddcf90944afdf21b 100644 --- a/lib/compiler_rt/parity.zig +++ b/lib/compiler_rt/parity.zig @@ -1,6 +1,7 @@ //! parity - if number of bits set is even => 0, else => 1 //! - pariytXi2_generic for big and little endian -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__paritysi2, "__paritysi2"); diff --git a/lib/compiler_rt/popcount.zig b/lib/compiler_rt/popcount.zig index b1ef500ea117514d08b598e4209770bd4b879b1f..3b9d867548f62d9ab7da321786cb737effa2646d 100644 --- a/lib/compiler_rt/popcount.zig +++ b/lib/compiler_rt/popcount.zig @@ -6,7 +6,8 @@ //! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, //! subsubsection "Working with the rightmost bits" and "Sideways addition". -const symbol = @import("../compiler_rt.zig").symbol; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__popcountsi2, "__popcountsi2"); diff --git a/lib/compiler_rt/powiXf2.zig b/lib/compiler_rt/powiXf2.zig index b2a1e3e6989ba85538243483d14fd92ad0e3158d..dd8b477f152144ce7206f4ce54caa77c1a4ead36 100644 --- a/lib/compiler_rt/powiXf2.zig +++ b/lib/compiler_rt/powiXf2.zig @@ -4,16 +4,18 @@ //! error propagation and this method is optimized for performance, not accuracy. const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { symbol(&__powihf2, "__powihf2"); symbol(&__powisf2, "__powisf2"); symbol(&__powidf2, "__powidf2"); - if (compiler_rt.want_ppc_abi) - symbol(&__powitf2, "__powikf2"); - symbol(&__powitf2, "__powitf2"); symbol(&__powixf2, "__powixf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__powitf2, "__powikf2"); + } else { + symbol(&__powitf2, "__powitf2"); + } } inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT { @@ -32,26 +34,41 @@ inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT { return if (is_recip) 1 / r else r; } -pub fn __powihf2(a: f16, b: i32) callconv(.c) f16 { +fn __powihf2(a: compiler_rt.f16.Abi, b: i32) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(powi_f16(compiler_rt.f16.fromAbi(a), b)); +} +pub fn powi_f16(a: f16, b: i32) f16 { return powiXf2(f16, a, b); } -pub fn __powisf2(a: f32, b: i32) callconv(.c) f32 { +fn __powisf2(a: compiler_rt.f32.Abi, b: i32) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(powi_f32(compiler_rt.f32.fromAbi(a), b)); +} +pub fn powi_f32(a: f32, b: i32) f32 { return powiXf2(f32, a, b); } -pub fn __powidf2(a: f64, b: i32) callconv(.c) f64 { +fn __powidf2(a: compiler_rt.f64.Abi, b: i32) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(powi_f64(compiler_rt.f64.fromAbi(a), b)); +} +pub fn powi_f64(a: f64, b: i32) f64 { return powiXf2(f64, a, b); } -pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 { - return powiXf2(f128, a, b); +fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b)); } - -pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 { +pub fn powi_f80(a: f80, b: i32) f80 { return powiXf2(f80, a, b); } +fn __powitf2(a: compiler_rt.f128.Abi, b: i32) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(powi_f128(compiler_rt.f128.fromAbi(a), b)); +} +pub fn powi_f128(a: f128, b: i32) f128 { + return powiXf2(f128, a, b); +} + test { _ = @import("powiXf2_test.zig"); } diff --git a/lib/compiler_rt/powiXf2_test.zig b/lib/compiler_rt/powiXf2_test.zig index 7bd43c73c3d2d1a379a6ef66977c55dff1fc8a00..1388a4e7250e7b418fee08cde6d165d2bce80adf 100644 --- a/lib/compiler_rt/powiXf2_test.zig +++ b/lib/compiler_rt/powiXf2_test.zig @@ -2,562 +2,568 @@ // powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c // powihf2 adapted from powisf2 tests -const powiXf2 = @import("powiXf2.zig"); const std = @import("std"); -const builtin = @import("builtin"); const testing = std.testing; const math = std.math; -fn test__powihf2(a: f16, b: i32, expected: f16) !void { - const result = powiXf2.__powihf2(a, b); +const impl = @import("powiXf2.zig"); + +const powi_f16 = impl.powi_f16; +const powi_f32 = impl.powi_f32; +const powi_f64 = impl.powi_f64; +const powi_f80 = impl.powi_f80; +const powi_f128 = impl.powi_f128; + +fn test_powi_f16(a: f16, b: i32, expected: f16) !void { + const result = powi_f16(a, b); try testing.expectEqual(expected, result); } -fn test__powisf2(a: f32, b: i32, expected: f32) !void { - const result = powiXf2.__powisf2(a, b); +fn test_powi_f32(a: f32, b: i32, expected: f32) !void { + const result = powi_f32(a, b); try testing.expectEqual(expected, result); } -fn test__powidf2(a: f64, b: i32, expected: f64) !void { - const result = powiXf2.__powidf2(a, b); +fn test_powi_f64(a: f64, b: i32, expected: f64) !void { + const result = powi_f64(a, b); try testing.expectEqual(expected, result); } -fn test__powitf2(a: f128, b: i32, expected: f128) !void { - const result = powiXf2.__powitf2(a, b); +fn test_powi_f80(a: f80, b: i32, expected: f80) !void { + const result = powi_f80(a, b); try testing.expectEqual(expected, result); } -fn test__powixf2(a: f80, b: i32, expected: f80) !void { - const result = powiXf2.__powixf2(a, b); +fn test_powi_f128(a: f128, b: i32, expected: f128) !void { + const result = powi_f128(a, b); try testing.expectEqual(expected, result); } -test "powihf2" { +test powi_f16 { const inf_f16 = math.inf(f16); - try test__powisf2(0, 0, 1); - try test__powihf2(1, 0, 1); - try test__powihf2(1.5, 0, 1); - try test__powihf2(2, 0, 1); - try test__powihf2(inf_f16, 0, 1); + try test_powi_f16(0, 0, 1); + try test_powi_f16(1, 0, 1); + try test_powi_f16(1.5, 0, 1); + try test_powi_f16(2, 0, 1); + try test_powi_f16(inf_f16, 0, 1); - try test__powihf2(-0.0, 0, 1); - try test__powihf2(-1, 0, 1); - try test__powihf2(-1.5, 0, 1); - try test__powihf2(-2, 0, 1); - try test__powihf2(-inf_f16, 0, 1); + try test_powi_f16(-0.0, 0, 1); + try test_powi_f16(-1, 0, 1); + try test_powi_f16(-1.5, 0, 1); + try test_powi_f16(-2, 0, 1); + try test_powi_f16(-inf_f16, 0, 1); - try test__powihf2(0, 1, 0); - try test__powihf2(0, 2, 0); - try test__powihf2(0, 3, 0); - try test__powihf2(0, 4, 0); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + try test_powi_f16(0, 1, 0); + try test_powi_f16(0, 2, 0); + try test_powi_f16(0, 3, 0); + try test_powi_f16(0, 4, 0); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - try test__powihf2(-0.0, 1, -0.0); - try test__powihf2(-0.0, 2, 0); - try test__powihf2(-0.0, 3, -0.0); - try test__powihf2(-0.0, 4, 0); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + try test_powi_f16(-0.0, 1, -0.0); + try test_powi_f16(-0.0, 2, 0); + try test_powi_f16(-0.0, 3, -0.0); + try test_powi_f16(-0.0, 4, 0); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - try test__powihf2(1, 1, 1); - try test__powihf2(1, 2, 1); - try test__powihf2(1, 3, 1); - try test__powihf2(1, 4, 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + try test_powi_f16(1, 1, 1); + try test_powi_f16(1, 2, 1); + try test_powi_f16(1, 3, 1); + try test_powi_f16(1, 4, 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - try test__powihf2(inf_f16, 1, inf_f16); - try test__powihf2(inf_f16, 2, inf_f16); - try test__powihf2(inf_f16, 3, inf_f16); - try test__powihf2(inf_f16, 4, inf_f16); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); + try test_powi_f16(inf_f16, 1, inf_f16); + try test_powi_f16(inf_f16, 2, inf_f16); + try test_powi_f16(inf_f16, 3, inf_f16); + try test_powi_f16(inf_f16, 4, inf_f16); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); - try test__powihf2(-inf_f16, 1, -inf_f16); - try test__powihf2(-inf_f16, 2, inf_f16); - try test__powihf2(-inf_f16, 3, -inf_f16); - try test__powihf2(-inf_f16, 4, inf_f16); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); + try test_powi_f16(-inf_f16, 1, -inf_f16); + try test_powi_f16(-inf_f16, 2, inf_f16); + try test_powi_f16(-inf_f16, 3, -inf_f16); + try test_powi_f16(-inf_f16, 4, inf_f16); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); // - try test__powihf2(0, -1, inf_f16); - try test__powihf2(0, -2, inf_f16); - try test__powihf2(0, -3, inf_f16); - try test__powihf2(0, -4, inf_f16); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); - try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); + try test_powi_f16(0, -1, inf_f16); + try test_powi_f16(0, -2, inf_f16); + try test_powi_f16(0, -3, inf_f16); + try test_powi_f16(0, -4, inf_f16); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); + try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); - try test__powihf2(-0.0, -1, -inf_f16); - try test__powihf2(-0.0, -2, inf_f16); - try test__powihf2(-0.0, -3, -inf_f16); - try test__powihf2(-0.0, -4, inf_f16); - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf - try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); + try test_powi_f16(-0.0, -1, -inf_f16); + try test_powi_f16(-0.0, -2, inf_f16); + try test_powi_f16(-0.0, -3, -inf_f16); + try test_powi_f16(-0.0, -4, inf_f16); + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf + try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); - try test__powihf2(1, -1, 1); - try test__powihf2(1, -2, 1); - try test__powihf2(1, -3, 1); - try test__powihf2(1, -4, 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + try test_powi_f16(1, -1, 1); + try test_powi_f16(1, -2, 1); + try test_powi_f16(1, -3, 1); + try test_powi_f16(1, -4, 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - try test__powihf2(inf_f16, -1, 0); - try test__powihf2(inf_f16, -2, 0); - try test__powihf2(inf_f16, -3, 0); - try test__powihf2(inf_f16, -4, 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f16(inf_f16, -1, 0); + try test_powi_f16(inf_f16, -2, 0); + try test_powi_f16(inf_f16, -3, 0); + try test_powi_f16(inf_f16, -4, 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); // - try test__powihf2(-inf_f16, -1, -0.0); - try test__powihf2(-inf_f16, -2, 0); - try test__powihf2(-inf_f16, -3, -0.0); - try test__powihf2(-inf_f16, -4, 0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f16(-inf_f16, -1, -0.0); + try test_powi_f16(-inf_f16, -2, 0); + try test_powi_f16(-inf_f16, -3, -0.0); + try test_powi_f16(-inf_f16, -4, 0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powihf2(2, 10, 1024.0); - try test__powihf2(-2, 10, 1024.0); - try test__powihf2(2, -10, 1.0 / 1024.0); - try test__powihf2(-2, -10, 1.0 / 1024.0); + try test_powi_f16(2, 10, 1024.0); + try test_powi_f16(-2, 10, 1024.0); + try test_powi_f16(2, -10, 1.0 / 1024.0); + try test_powi_f16(-2, -10, 1.0 / 1024.0); - try test__powihf2(2, 14, 16384.0); - try test__powihf2(-2, 14, 16384.0); - try test__powihf2(2, 15, 32768.0); - try test__powihf2(-2, 15, -32768.0); - try test__powihf2(2, 16, inf_f16); - try test__powihf2(-2, 16, inf_f16); + try test_powi_f16(2, 14, 16384.0); + try test_powi_f16(-2, 14, 16384.0); + try test_powi_f16(2, 15, 32768.0); + try test_powi_f16(-2, 15, -32768.0); + try test_powi_f16(2, 16, inf_f16); + try test_powi_f16(-2, 16, inf_f16); - try test__powihf2(2, -13, 1.0 / 8192.0); - try test__powihf2(-2, -13, -1.0 / 8192.0); - try test__powihf2(2, -15, 1.0 / 32768.0); - try test__powihf2(-2, -15, -1.0 / 32768.0); - try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) - try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) + try test_powi_f16(2, -13, 1.0 / 8192.0); + try test_powi_f16(-2, -13, -1.0 / 8192.0); + try test_powi_f16(2, -15, 1.0 / 32768.0); + try test_powi_f16(-2, -15, -1.0 / 32768.0); + try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) + try test_powi_f16(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) } -test "powisf2" { +test powi_f32 { const inf_f32 = math.inf(f32); - try test__powisf2(0, 0, 1); - try test__powisf2(1, 0, 1); - try test__powisf2(1.5, 0, 1); - try test__powisf2(2, 0, 1); - try test__powisf2(inf_f32, 0, 1); + try test_powi_f32(0, 0, 1); + try test_powi_f32(1, 0, 1); + try test_powi_f32(1.5, 0, 1); + try test_powi_f32(2, 0, 1); + try test_powi_f32(inf_f32, 0, 1); - try test__powisf2(-0.0, 0, 1); - try test__powisf2(-1, 0, 1); - try test__powisf2(-1.5, 0, 1); - try test__powisf2(-2, 0, 1); - try test__powisf2(-inf_f32, 0, 1); + try test_powi_f32(-0.0, 0, 1); + try test_powi_f32(-1, 0, 1); + try test_powi_f32(-1.5, 0, 1); + try test_powi_f32(-2, 0, 1); + try test_powi_f32(-inf_f32, 0, 1); - try test__powisf2(0, 1, 0); - try test__powisf2(0, 2, 0); - try test__powisf2(0, 3, 0); - try test__powisf2(0, 4, 0); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + try test_powi_f32(0, 1, 0); + try test_powi_f32(0, 2, 0); + try test_powi_f32(0, 3, 0); + try test_powi_f32(0, 4, 0); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - try test__powisf2(-0.0, 1, -0.0); - try test__powisf2(-0.0, 2, 0); - try test__powisf2(-0.0, 3, -0.0); - try test__powisf2(-0.0, 4, 0); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + try test_powi_f32(-0.0, 1, -0.0); + try test_powi_f32(-0.0, 2, 0); + try test_powi_f32(-0.0, 3, -0.0); + try test_powi_f32(-0.0, 4, 0); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - try test__powisf2(1, 1, 1); - try test__powisf2(1, 2, 1); - try test__powisf2(1, 3, 1); - try test__powisf2(1, 4, 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + try test_powi_f32(1, 1, 1); + try test_powi_f32(1, 2, 1); + try test_powi_f32(1, 3, 1); + try test_powi_f32(1, 4, 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - try test__powisf2(inf_f32, 1, inf_f32); - try test__powisf2(inf_f32, 2, inf_f32); - try test__powisf2(inf_f32, 3, inf_f32); - try test__powisf2(inf_f32, 4, inf_f32); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); + try test_powi_f32(inf_f32, 1, inf_f32); + try test_powi_f32(inf_f32, 2, inf_f32); + try test_powi_f32(inf_f32, 3, inf_f32); + try test_powi_f32(inf_f32, 4, inf_f32); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); - try test__powisf2(-inf_f32, 1, -inf_f32); - try test__powisf2(-inf_f32, 2, inf_f32); - try test__powisf2(-inf_f32, 3, -inf_f32); - try test__powisf2(-inf_f32, 4, inf_f32); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); + try test_powi_f32(-inf_f32, 1, -inf_f32); + try test_powi_f32(-inf_f32, 2, inf_f32); + try test_powi_f32(-inf_f32, 3, -inf_f32); + try test_powi_f32(-inf_f32, 4, inf_f32); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); - try test__powisf2(0, -1, inf_f32); - try test__powisf2(0, -2, inf_f32); - try test__powisf2(0, -3, inf_f32); - try test__powisf2(0, -4, inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); - try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); + try test_powi_f32(0, -1, inf_f32); + try test_powi_f32(0, -2, inf_f32); + try test_powi_f32(0, -3, inf_f32); + try test_powi_f32(0, -4, inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); + try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); - try test__powisf2(-0.0, -1, -inf_f32); - try test__powisf2(-0.0, -2, inf_f32); - try test__powisf2(-0.0, -3, -inf_f32); - try test__powisf2(-0.0, -4, inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); - try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); + try test_powi_f32(-0.0, -1, -inf_f32); + try test_powi_f32(-0.0, -2, inf_f32); + try test_powi_f32(-0.0, -3, -inf_f32); + try test_powi_f32(-0.0, -4, inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); + try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); - try test__powisf2(1, -1, 1); - try test__powisf2(1, -2, 1); - try test__powisf2(1, -3, 1); - try test__powisf2(1, -4, 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + try test_powi_f32(1, -1, 1); + try test_powi_f32(1, -2, 1); + try test_powi_f32(1, -3, 1); + try test_powi_f32(1, -4, 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - try test__powisf2(inf_f32, -1, 0); - try test__powisf2(inf_f32, -2, 0); - try test__powisf2(inf_f32, -3, 0); - try test__powisf2(inf_f32, -4, 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f32(inf_f32, -1, 0); + try test_powi_f32(inf_f32, -2, 0); + try test_powi_f32(inf_f32, -3, 0); + try test_powi_f32(inf_f32, -4, 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powisf2(-inf_f32, -1, -0.0); - try test__powisf2(-inf_f32, -2, 0); - try test__powisf2(-inf_f32, -3, -0.0); - try test__powisf2(-inf_f32, -4, 0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + try test_powi_f32(-inf_f32, -1, -0.0); + try test_powi_f32(-inf_f32, -2, 0); + try test_powi_f32(-inf_f32, -3, -0.0); + try test_powi_f32(-inf_f32, -4, 0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - try test__powisf2(2.0, 10, 1024.0); - try test__powisf2(-2, 10, 1024.0); - try test__powisf2(2, -10, 1.0 / 1024.0); - try test__powisf2(-2, -10, 1.0 / 1024.0); + try test_powi_f32(2.0, 10, 1024.0); + try test_powi_f32(-2, 10, 1024.0); + try test_powi_f32(2, -10, 1.0 / 1024.0); + try test_powi_f32(-2, -10, 1.0 / 1024.0); // - try test__powisf2(2, 19, 524288.0); - try test__powisf2(-2, 19, -524288.0); - try test__powisf2(2, -19, 1.0 / 524288.0); - try test__powisf2(-2, -19, -1.0 / 524288.0); + try test_powi_f32(2, 19, 524288.0); + try test_powi_f32(-2, 19, -524288.0); + try test_powi_f32(2, -19, 1.0 / 524288.0); + try test_powi_f32(-2, -19, -1.0 / 524288.0); - try test__powisf2(2, 31, 2147483648.0); - try test__powisf2(-2, 31, -2147483648.0); - try test__powisf2(2, -31, 1.0 / 2147483648.0); - try test__powisf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f32(2, 31, 2147483648.0); + try test_powi_f32(-2, 31, -2147483648.0); + try test_powi_f32(2, -31, 1.0 / 2147483648.0); + try test_powi_f32(-2, -31, -1.0 / 2147483648.0); } -test "powidf2" { +test powi_f64 { const inf_f64 = math.inf(f64); - try test__powidf2(0, 0, 1); - try test__powidf2(1, 0, 1); - try test__powidf2(1.5, 0, 1); - try test__powidf2(2, 0, 1); - try test__powidf2(inf_f64, 0, 1); - - try test__powidf2(-0.0, 0, 1); - try test__powidf2(-1, 0, 1); - try test__powidf2(-1.5, 0, 1); - try test__powidf2(-2, 0, 1); - try test__powidf2(-inf_f64, 0, 1); - - try test__powidf2(0, 1, 0); - try test__powidf2(0, 2, 0); - try test__powidf2(0, 3, 0); - try test__powidf2(0, 4, 0); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - - try test__powidf2(-0.0, 1, -0.0); - try test__powidf2(-0.0, 2, 0); - try test__powidf2(-0.0, 3, -0.0); - try test__powidf2(-0.0, 4, 0); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powidf2(1, 1, 1); - try test__powidf2(1, 2, 1); - try test__powidf2(1, 3, 1); - try test__powidf2(1, 4, 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powidf2(inf_f64, 1, inf_f64); - try test__powidf2(inf_f64, 2, inf_f64); - try test__powidf2(inf_f64, 3, inf_f64); - try test__powidf2(inf_f64, 4, inf_f64); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); - - try test__powidf2(-inf_f64, 1, -inf_f64); - try test__powidf2(-inf_f64, 2, inf_f64); - try test__powidf2(-inf_f64, 3, -inf_f64); - try test__powidf2(-inf_f64, 4, inf_f64); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); - - try test__powidf2(0, -1, inf_f64); - try test__powidf2(0, -2, inf_f64); - try test__powidf2(0, -3, inf_f64); - try test__powidf2(0, -4, inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); - try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); - - try test__powidf2(-0.0, -1, -inf_f64); - try test__powidf2(-0.0, -2, inf_f64); - try test__powidf2(-0.0, -3, -inf_f64); - try test__powidf2(-0.0, -4, inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); - try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); - - try test__powidf2(1, -1, 1); - try test__powidf2(1, -2, 1); - try test__powidf2(1, -3, 1); - try test__powidf2(1, -4, 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powidf2(inf_f64, -1, 0); - try test__powidf2(inf_f64, -2, 0); - try test__powidf2(inf_f64, -3, 0); - try test__powidf2(inf_f64, -4, 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powidf2(-inf_f64, -1, -0.0); - try test__powidf2(-inf_f64, -2, 0); - try test__powidf2(-inf_f64, -3, -0.0); - try test__powidf2(-inf_f64, -4, 0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powidf2(2, 10, 1024.0); - try test__powidf2(-2, 10, 1024.0); - try test__powidf2(2, -10, 1.0 / 1024.0); - try test__powidf2(-2, -10, 1.0 / 1024.0); - - try test__powidf2(2, 19, 524288.0); - try test__powidf2(-2, 19, -524288.0); - try test__powidf2(2, -19, 1.0 / 524288.0); - try test__powidf2(-2, -19, -1.0 / 524288.0); - - try test__powidf2(2, 31, 2147483648.0); - try test__powidf2(-2, 31, -2147483648.0); - try test__powidf2(2, -31, 1.0 / 2147483648.0); - try test__powidf2(-2, -31, -1.0 / 2147483648.0); -} - -test "powitf2" { - const inf_f128 = math.inf(f128); - try test__powitf2(0, 0, 1); - try test__powitf2(1, 0, 1); - try test__powitf2(1.5, 0, 1); - try test__powitf2(2, 0, 1); - try test__powitf2(inf_f128, 0, 1); - - try test__powitf2(-0.0, 0, 1); - try test__powitf2(-1, 0, 1); - try test__powitf2(-1.5, 0, 1); - try test__powitf2(-2, 0, 1); - try test__powitf2(-inf_f128, 0, 1); - - try test__powitf2(0, 1, 0); - try test__powitf2(0, 2, 0); - try test__powitf2(0, 3, 0); - try test__powitf2(0, 4, 0); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powitf2(0, 0x7FFFFFFF, 0); - - try test__powitf2(-0.0, 1, -0.0); - try test__powitf2(-0.0, 2, 0); - try test__powitf2(-0.0, 3, -0.0); - try test__powitf2(-0.0, 4, 0); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powitf2(1, 1, 1); - try test__powitf2(1, 2, 1); - try test__powitf2(1, 3, 1); - try test__powitf2(1, 4, 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powitf2(inf_f128, 1, inf_f128); - try test__powitf2(inf_f128, 2, inf_f128); - try test__powitf2(inf_f128, 3, inf_f128); - try test__powitf2(inf_f128, 4, inf_f128); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); - - try test__powitf2(-inf_f128, 1, -inf_f128); - try test__powitf2(-inf_f128, 2, inf_f128); - try test__powitf2(-inf_f128, 3, -inf_f128); - try test__powitf2(-inf_f128, 4, inf_f128); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); - - try test__powitf2(0, -1, inf_f128); - try test__powitf2(0, -2, inf_f128); - try test__powitf2(0, -3, inf_f128); - try test__powitf2(0, -4, inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); - try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); - - try test__powitf2(-0.0, -1, -inf_f128); - try test__powitf2(-0.0, -2, inf_f128); - try test__powitf2(-0.0, -3, -inf_f128); - try test__powitf2(-0.0, -4, inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); - try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); - - try test__powitf2(1, -1, 1); - try test__powitf2(1, -2, 1); - try test__powitf2(1, -3, 1); - try test__powitf2(1, -4, 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powitf2(inf_f128, -1, 0); - try test__powitf2(inf_f128, -2, 0); - try test__powitf2(inf_f128, -3, 0); - try test__powitf2(inf_f128, -4, 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powitf2(-inf_f128, -1, -0.0); - try test__powitf2(-inf_f128, -2, 0); - try test__powitf2(-inf_f128, -3, -0.0); - try test__powitf2(-inf_f128, -4, 0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powitf2(2, 10, 1024.0); - try test__powitf2(-2, 10, 1024.0); - try test__powitf2(2, -10, 1.0 / 1024.0); - try test__powitf2(-2, -10, 1.0 / 1024.0); - - try test__powitf2(2, 19, 524288.0); - try test__powitf2(-2, 19, -524288.0); - try test__powitf2(2, -19, 1.0 / 524288.0); - try test__powitf2(-2, -19, -1.0 / 524288.0); - - try test__powitf2(2, 31, 2147483648.0); - try test__powitf2(-2, 31, -2147483648.0); - try test__powitf2(2, -31, 1.0 / 2147483648.0); - try test__powitf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f64(0, 0, 1); + try test_powi_f64(1, 0, 1); + try test_powi_f64(1.5, 0, 1); + try test_powi_f64(2, 0, 1); + try test_powi_f64(inf_f64, 0, 1); + + try test_powi_f64(-0.0, 0, 1); + try test_powi_f64(-1, 0, 1); + try test_powi_f64(-1.5, 0, 1); + try test_powi_f64(-2, 0, 1); + try test_powi_f64(-inf_f64, 0, 1); + + try test_powi_f64(0, 1, 0); + try test_powi_f64(0, 2, 0); + try test_powi_f64(0, 3, 0); + try test_powi_f64(0, 4, 0); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + + try test_powi_f64(-0.0, 1, -0.0); + try test_powi_f64(-0.0, 2, 0); + try test_powi_f64(-0.0, 3, -0.0); + try test_powi_f64(-0.0, 4, 0); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f64(1, 1, 1); + try test_powi_f64(1, 2, 1); + try test_powi_f64(1, 3, 1); + try test_powi_f64(1, 4, 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f64(inf_f64, 1, inf_f64); + try test_powi_f64(inf_f64, 2, inf_f64); + try test_powi_f64(inf_f64, 3, inf_f64); + try test_powi_f64(inf_f64, 4, inf_f64); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); + + try test_powi_f64(-inf_f64, 1, -inf_f64); + try test_powi_f64(-inf_f64, 2, inf_f64); + try test_powi_f64(-inf_f64, 3, -inf_f64); + try test_powi_f64(-inf_f64, 4, inf_f64); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); + + try test_powi_f64(0, -1, inf_f64); + try test_powi_f64(0, -2, inf_f64); + try test_powi_f64(0, -3, inf_f64); + try test_powi_f64(0, -4, inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); + try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); + + try test_powi_f64(-0.0, -1, -inf_f64); + try test_powi_f64(-0.0, -2, inf_f64); + try test_powi_f64(-0.0, -3, -inf_f64); + try test_powi_f64(-0.0, -4, inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); + try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); + + try test_powi_f64(1, -1, 1); + try test_powi_f64(1, -2, 1); + try test_powi_f64(1, -3, 1); + try test_powi_f64(1, -4, 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f64(inf_f64, -1, 0); + try test_powi_f64(inf_f64, -2, 0); + try test_powi_f64(inf_f64, -3, 0); + try test_powi_f64(inf_f64, -4, 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f64(-inf_f64, -1, -0.0); + try test_powi_f64(-inf_f64, -2, 0); + try test_powi_f64(-inf_f64, -3, -0.0); + try test_powi_f64(-inf_f64, -4, 0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f64(2, 10, 1024.0); + try test_powi_f64(-2, 10, 1024.0); + try test_powi_f64(2, -10, 1.0 / 1024.0); + try test_powi_f64(-2, -10, 1.0 / 1024.0); + + try test_powi_f64(2, 19, 524288.0); + try test_powi_f64(-2, 19, -524288.0); + try test_powi_f64(2, -19, 1.0 / 524288.0); + try test_powi_f64(-2, -19, -1.0 / 524288.0); + + try test_powi_f64(2, 31, 2147483648.0); + try test_powi_f64(-2, 31, -2147483648.0); + try test_powi_f64(2, -31, 1.0 / 2147483648.0); + try test_powi_f64(-2, -31, -1.0 / 2147483648.0); } -test "powixf2" { +test powi_f80 { const inf_f80 = math.inf(f80); - try test__powixf2(0, 0, 1); - try test__powixf2(1, 0, 1); - try test__powixf2(1.5, 0, 1); - try test__powixf2(2, 0, 1); - try test__powixf2(inf_f80, 0, 1); - - try test__powixf2(-0.0, 0, 1); - try test__powixf2(-1, 0, 1); - try test__powixf2(-1.5, 0, 1); - try test__powixf2(-2, 0, 1); - try test__powixf2(-inf_f80, 0, 1); - - try test__powixf2(0, 1, 0); - try test__powixf2(0, 2, 0); - try test__powixf2(0, 3, 0); - try test__powixf2(0, 4, 0); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); - - try test__powixf2(-0.0, 1, -0.0); - try test__powixf2(-0.0, 2, 0); - try test__powixf2(-0.0, 3, -0.0); - try test__powixf2(-0.0, 4, 0); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); - - try test__powixf2(1, 1, 1); - try test__powixf2(1, 2, 1); - try test__powixf2(1, 3, 1); - try test__powixf2(1, 4, 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); - - try test__powixf2(inf_f80, 1, inf_f80); - try test__powixf2(inf_f80, 2, inf_f80); - try test__powixf2(inf_f80, 3, inf_f80); - try test__powixf2(inf_f80, 4, inf_f80); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); - - try test__powixf2(-inf_f80, 1, -inf_f80); - try test__powixf2(-inf_f80, 2, inf_f80); - try test__powixf2(-inf_f80, 3, -inf_f80); - try test__powixf2(-inf_f80, 4, inf_f80); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); - - try test__powixf2(0, -1, inf_f80); - try test__powixf2(0, -2, inf_f80); - try test__powixf2(0, -3, inf_f80); - try test__powixf2(0, -4, inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); - try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); - - try test__powixf2(-0.0, -1, -inf_f80); - try test__powixf2(-0.0, -2, inf_f80); - try test__powixf2(-0.0, -3, -inf_f80); - try test__powixf2(-0.0, -4, inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); - try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); - - try test__powixf2(1, -1, 1); - try test__powixf2(1, -2, 1); - try test__powixf2(1, -3, 1); - try test__powixf2(1, -4, 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); - try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); - - try test__powixf2(inf_f80, -1, 0); - try test__powixf2(inf_f80, -2, 0); - try test__powixf2(inf_f80, -3, 0); - try test__powixf2(inf_f80, -4, 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); - try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powixf2(-inf_f80, -1, -0.0); - try test__powixf2(-inf_f80, -2, 0); - try test__powixf2(-inf_f80, -3, -0.0); - try test__powixf2(-inf_f80, -4, 0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); - try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); - - try test__powixf2(2, 10, 1024.0); - try test__powixf2(-2, 10, 1024.0); - try test__powixf2(2, -10, 1.0 / 1024.0); - try test__powixf2(-2, -10, 1.0 / 1024.0); - - try test__powixf2(2, 19, 524288.0); - try test__powixf2(-2, 19, -524288.0); - try test__powixf2(2, -19, 1.0 / 524288.0); - try test__powixf2(-2, -19, -1.0 / 524288.0); - - try test__powixf2(2, 31, 2147483648.0); - try test__powixf2(-2, 31, -2147483648.0); - try test__powixf2(2, -31, 1.0 / 2147483648.0); - try test__powixf2(-2, -31, -1.0 / 2147483648.0); + try test_powi_f80(0, 0, 1); + try test_powi_f80(1, 0, 1); + try test_powi_f80(1.5, 0, 1); + try test_powi_f80(2, 0, 1); + try test_powi_f80(inf_f80, 0, 1); + + try test_powi_f80(-0.0, 0, 1); + try test_powi_f80(-1, 0, 1); + try test_powi_f80(-1.5, 0, 1); + try test_powi_f80(-2, 0, 1); + try test_powi_f80(-inf_f80, 0, 1); + + try test_powi_f80(0, 1, 0); + try test_powi_f80(0, 2, 0); + try test_powi_f80(0, 3, 0); + try test_powi_f80(0, 4, 0); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); + + try test_powi_f80(-0.0, 1, -0.0); + try test_powi_f80(-0.0, 2, 0); + try test_powi_f80(-0.0, 3, -0.0); + try test_powi_f80(-0.0, 4, 0); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f80(1, 1, 1); + try test_powi_f80(1, 2, 1); + try test_powi_f80(1, 3, 1); + try test_powi_f80(1, 4, 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f80(inf_f80, 1, inf_f80); + try test_powi_f80(inf_f80, 2, inf_f80); + try test_powi_f80(inf_f80, 3, inf_f80); + try test_powi_f80(inf_f80, 4, inf_f80); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); + + try test_powi_f80(-inf_f80, 1, -inf_f80); + try test_powi_f80(-inf_f80, 2, inf_f80); + try test_powi_f80(-inf_f80, 3, -inf_f80); + try test_powi_f80(-inf_f80, 4, inf_f80); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); + + try test_powi_f80(0, -1, inf_f80); + try test_powi_f80(0, -2, inf_f80); + try test_powi_f80(0, -3, inf_f80); + try test_powi_f80(0, -4, inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); + try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); + + try test_powi_f80(-0.0, -1, -inf_f80); + try test_powi_f80(-0.0, -2, inf_f80); + try test_powi_f80(-0.0, -3, -inf_f80); + try test_powi_f80(-0.0, -4, inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); + try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); + + try test_powi_f80(1, -1, 1); + try test_powi_f80(1, -2, 1); + try test_powi_f80(1, -3, 1); + try test_powi_f80(1, -4, 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f80(inf_f80, -1, 0); + try test_powi_f80(inf_f80, -2, 0); + try test_powi_f80(inf_f80, -3, 0); + try test_powi_f80(inf_f80, -4, 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f80(-inf_f80, -1, -0.0); + try test_powi_f80(-inf_f80, -2, 0); + try test_powi_f80(-inf_f80, -3, -0.0); + try test_powi_f80(-inf_f80, -4, 0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f80(2, 10, 1024.0); + try test_powi_f80(-2, 10, 1024.0); + try test_powi_f80(2, -10, 1.0 / 1024.0); + try test_powi_f80(-2, -10, 1.0 / 1024.0); + + try test_powi_f80(2, 19, 524288.0); + try test_powi_f80(-2, 19, -524288.0); + try test_powi_f80(2, -19, 1.0 / 524288.0); + try test_powi_f80(-2, -19, -1.0 / 524288.0); + + try test_powi_f80(2, 31, 2147483648.0); + try test_powi_f80(-2, 31, -2147483648.0); + try test_powi_f80(2, -31, 1.0 / 2147483648.0); + try test_powi_f80(-2, -31, -1.0 / 2147483648.0); +} + +test powi_f128 { + const inf_f128 = math.inf(f128); + try test_powi_f128(0, 0, 1); + try test_powi_f128(1, 0, 1); + try test_powi_f128(1.5, 0, 1); + try test_powi_f128(2, 0, 1); + try test_powi_f128(inf_f128, 0, 1); + + try test_powi_f128(-0.0, 0, 1); + try test_powi_f128(-1, 0, 1); + try test_powi_f128(-1.5, 0, 1); + try test_powi_f128(-2, 0, 1); + try test_powi_f128(-inf_f128, 0, 1); + + try test_powi_f128(0, 1, 0); + try test_powi_f128(0, 2, 0); + try test_powi_f128(0, 3, 0); + try test_powi_f128(0, 4, 0); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f128(0, 0x7FFFFFFF, 0); + + try test_powi_f128(-0.0, 1, -0.0); + try test_powi_f128(-0.0, 2, 0); + try test_powi_f128(-0.0, 3, -0.0); + try test_powi_f128(-0.0, 4, 0); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); + + try test_powi_f128(1, 1, 1); + try test_powi_f128(1, 2, 1); + try test_powi_f128(1, 3, 1); + try test_powi_f128(1, 4, 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); + + try test_powi_f128(inf_f128, 1, inf_f128); + try test_powi_f128(inf_f128, 2, inf_f128); + try test_powi_f128(inf_f128, 3, inf_f128); + try test_powi_f128(inf_f128, 4, inf_f128); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); + + try test_powi_f128(-inf_f128, 1, -inf_f128); + try test_powi_f128(-inf_f128, 2, inf_f128); + try test_powi_f128(-inf_f128, 3, -inf_f128); + try test_powi_f128(-inf_f128, 4, inf_f128); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); + + try test_powi_f128(0, -1, inf_f128); + try test_powi_f128(0, -2, inf_f128); + try test_powi_f128(0, -3, inf_f128); + try test_powi_f128(0, -4, inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); + try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); + + try test_powi_f128(-0.0, -1, -inf_f128); + try test_powi_f128(-0.0, -2, inf_f128); + try test_powi_f128(-0.0, -3, -inf_f128); + try test_powi_f128(-0.0, -4, inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); + try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); + + try test_powi_f128(1, -1, 1); + try test_powi_f128(1, -2, 1); + try test_powi_f128(1, -3, 1); + try test_powi_f128(1, -4, 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); + try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); + + try test_powi_f128(inf_f128, -1, 0); + try test_powi_f128(inf_f128, -2, 0); + try test_powi_f128(inf_f128, -3, 0); + try test_powi_f128(inf_f128, -4, 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); + try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f128(-inf_f128, -1, -0.0); + try test_powi_f128(-inf_f128, -2, 0); + try test_powi_f128(-inf_f128, -3, -0.0); + try test_powi_f128(-inf_f128, -4, 0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); + try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); + + try test_powi_f128(2, 10, 1024.0); + try test_powi_f128(-2, 10, 1024.0); + try test_powi_f128(2, -10, 1.0 / 1024.0); + try test_powi_f128(-2, -10, 1.0 / 1024.0); + + try test_powi_f128(2, 19, 524288.0); + try test_powi_f128(-2, 19, -524288.0); + try test_powi_f128(2, -19, 1.0 / 524288.0); + try test_powi_f128(-2, -19, -1.0 / 524288.0); + + try test_powi_f128(2, 31, 2147483648.0); + try test_powi_f128(-2, 31, -2147483648.0); + try test_powi_f128(2, -31, 1.0 / 2147483648.0); + try test_powi_f128(-2, -31, -1.0 / 2147483648.0); } diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 590b957922efdbf33ac4fea2728390daad82ee38..6c86984605af2d246a4e582851a5d172a67d7c69 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -18,19 +18,23 @@ comptime { symbol(&roundf, "roundf"); symbol(&round, "round"); symbol(&__roundx, "__roundx"); - if (compiler_rt.want_ppc_abi) { - symbol(&roundq, "roundf128"); - } + if (compiler_rt.want_ppc_abi) symbol(&roundq, "roundf128"); symbol(&roundq, "roundq"); symbol(&roundl, "roundl"); } -pub fn __roundh(x: f16) callconv(.c) f16 { +fn __roundh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(round_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn round_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(roundf(x)); + return @floatCast(round_f32(x)); } -pub fn roundf(x_: f32) callconv(.c) f32 { +fn roundf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(round_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn round_f32(x_: f32) f32 { const f32_toint = 1.0 / math.floatEps(f32); var x = x_; @@ -65,7 +69,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 { } } -pub fn round(x_: f64) callconv(.c) f64 { +fn round(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(round_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn round_f64(x_: f64) f64 { const f64_toint = 1.0 / math.floatEps(f64); var x = x_; @@ -100,12 +107,18 @@ pub fn round(x_: f64) callconv(.c) f64 { } } -pub fn __roundx(x: f80) callconv(.c) f80 { +fn __roundx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(round_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn round_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(roundq(x)); + return @floatCast(round_f128(x)); } -pub fn roundq(x_: f128) callconv(.c) f128 { +fn roundq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(round_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn round_f128(x_: f128) f128 { const f128_toint = 1.0 / math.floatEps(f128); var x = x_; @@ -142,54 +155,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 { pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return round(x), - 80 => return __roundx(x), - 128 => return roundq(x), - else => @compileError("unreachable"), + 64 => return round_f64(x), + 80 => return round_f80(x), + 128 => return round_f128(x), + else => comptime unreachable, } } -test "round32" { - try expect(roundf(1.3) == 1.0); - try expect(roundf(-1.3) == -1.0); - try expect(roundf(0.2) == 0.0); - try expect(roundf(1.8) == 2.0); +test round_f16 { + try expect(round_f16(1.3) == 1.0); + try expect(round_f16(-1.3) == -1.0); + try expect(round_f16(1.8) == 2.0); + try expect(round_f16(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f16(0.2))); + try expect(math.isNegativeZero(round_f16(-0.2))); + try expect(math.isPositiveZero(round_f16(0.0))); + try expect(math.isNegativeZero(round_f16(-0.0))); + try expect(math.isPositiveInf(round_f16(math.inf(f32)))); + try expect(math.isNegativeInf(round_f16(-math.inf(f32)))); + try expect(math.isNan(round_f16(math.nan(f32)))); } -test "round64" { - try expect(round(1.3) == 1.0); - try expect(round(-1.3) == -1.0); - try expect(round(0.2) == 0.0); - try expect(round(1.8) == 2.0); +test round_f32 { + try expect(round_f32(1.3) == 1.0); + try expect(round_f32(-1.3) == -1.0); + try expect(round_f32(1.8) == 2.0); + try expect(round_f32(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f32(0.2))); + try expect(math.isNegativeZero(round_f32(-0.2))); + try expect(math.isPositiveZero(round_f32(0.0))); + try expect(math.isNegativeZero(round_f32(-0.0))); + try expect(math.isPositiveInf(round_f32(math.inf(f32)))); + try expect(math.isNegativeInf(round_f32(-math.inf(f32)))); + try expect(math.isNan(round_f32(math.nan(f32)))); } -test "round128" { - try expect(roundq(1.3) == 1.0); - try expect(roundq(-1.3) == -1.0); - try expect(roundq(0.2) == 0.0); - try expect(roundq(1.8) == 2.0); +test round_f64 { + try expect(round_f64(1.3) == 1.0); + try expect(round_f64(-1.3) == -1.0); + try expect(round_f64(1.8) == 2.0); + try expect(round_f64(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f64(0.2))); + try expect(math.isNegativeZero(round_f64(-0.2))); + try expect(math.isPositiveZero(round_f64(0.0))); + try expect(math.isNegativeZero(round_f64(-0.0))); + try expect(math.isPositiveInf(round_f64(math.inf(f64)))); + try expect(math.isNegativeInf(round_f64(-math.inf(f64)))); + try expect(math.isNan(round_f64(math.nan(f64)))); } -test "round32.special" { - try expect(roundf(0.0) == 0.0); - try expect(roundf(-0.0) == -0.0); - try expect(math.isPositiveInf(roundf(math.inf(f32)))); - try expect(math.isNegativeInf(roundf(-math.inf(f32)))); - try expect(math.isNan(roundf(math.nan(f32)))); +test round_f80 { + try expect(round_f80(1.3) == 1.0); + try expect(round_f80(-1.3) == -1.0); + try expect(round_f80(1.8) == 2.0); + try expect(round_f80(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f80(0.2))); + try expect(math.isNegativeZero(round_f80(-0.2))); + try expect(math.isPositiveZero(round_f80(0.0))); + try expect(math.isNegativeZero(round_f80(-0.0))); + try expect(math.isPositiveInf(round_f80(math.inf(f64)))); + try expect(math.isNegativeInf(round_f80(-math.inf(f64)))); + try expect(math.isNan(round_f80(math.nan(f64)))); } -test "round64.special" { - try expect(round(0.0) == 0.0); - try expect(round(-0.0) == -0.0); - try expect(math.isPositiveInf(round(math.inf(f64)))); - try expect(math.isNegativeInf(round(-math.inf(f64)))); - try expect(math.isNan(round(math.nan(f64)))); -} - -test "round128.special" { - try expect(roundq(0.0) == 0.0); - try expect(roundq(-0.0) == -0.0); - try expect(math.isPositiveInf(roundq(math.inf(f128)))); - try expect(math.isNegativeInf(roundq(-math.inf(f128)))); - try expect(math.isNan(roundq(math.nan(f128)))); +test round_f128 { + try expect(round_f128(1.3) == 1.0); + try expect(round_f128(-1.3) == -1.0); + try expect(round_f128(1.8) == 2.0); + try expect(round_f128(-1.8) == -2.0); + try expect(math.isPositiveZero(round_f128(0.2))); + try expect(math.isNegativeZero(round_f128(-0.2))); + try expect(math.isPositiveZero(round_f128(0.0))); + try expect(math.isNegativeZero(round_f128(-0.0))); + try expect(math.isPositiveInf(round_f128(math.inf(f128)))); + try expect(math.isNegativeInf(round_f128(-math.inf(f128)))); + try expect(math.isNan(round_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index 040cba8cd3ef34e59f6bfd181a3c09036963fb4c..fe818922fe4af6542dc88fd682367860ae4908da 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -13,31 +13,37 @@ const expect = std.testing.expect; const expectApproxEqAbs = std.testing.expectApproxEqAbs; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; comptime { - symbol(&sinh, "__sinh"); - symbol(&sinl, "__sinl"); + symbol(&__sinh, "__sinh"); symbol(&sinf, "sinf"); symbol(&sin, "sin"); - symbol(&sinx, "__sinx"); + symbol(&__sinx, "__sinx"); if (compiler_rt.want_ppc_abi) { symbol(&sinq, "sinf128"); } symbol(&sinq, "sinq"); symbol(&sinl, "sinl"); + symbol(&sinl, "__sinl"); // required by musl } -pub fn sinh(x: f16) callconv(.c) f16 { +fn __sinh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sin_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn sin_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(sinf(x)); + return @floatCast(sin_f32(x)); } -pub fn sinf(x: f32) callconv(.c) f32 { +fn sinf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sin_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn sin_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -98,7 +104,10 @@ pub fn sinf(x: f32) callconv(.c) f32 { }; } -pub fn sin(x: f64) callconv(.c) f64 { +fn sin(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sin_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn sin_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -133,7 +142,10 @@ pub fn sin(x: f64) callconv(.c) f64 { }; } -fn sinx(x: f80) callconv(.c) f80 { +fn __sinx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sin_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn sin_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -160,7 +172,10 @@ fn sinx(x: f80) callconv(.c) f80 { }; } -pub fn sinq(x: f128) callconv(.c) f128 { +fn sinq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sin_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn sin_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -189,20 +204,21 @@ pub fn sinq(x: f128) callconv(.c) f128 { pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sin(x), - 80 => return sinx(x), - 128 => return sinq(x), - else => @compileError("unreachable"), + 64 => return sin_f64(x), + 80 => return sin_f80(x), + 128 => return sin_f128(x), + else => comptime unreachable, } } fn testSinSpecial(comptime T: type) !void { const f = switch (T) { - f32 => sinf, - f64 => sin, - f80 => sinx, - f128 => sinq, - else => @compileError("unimplemented"), + f16 => sin_f16, + f32 => sin_f32, + f64 => sin_f64, + f80 => sin_f80, + f128 => sin_f128, + else => comptime unreachable, }; try expect(math.isPositiveZero(f(0.0))); @@ -214,13 +230,13 @@ fn testSinSpecial(comptime T: type) !void { test "sin32.normal" { const epsilon = math.floatEps(f32); - try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon); - try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon); - try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon); - try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon); - try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon); - try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon); - try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon); + try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon); + try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon); + try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon); + try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon); + try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon); + try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon); + try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon); } test "sin32.special" { @@ -229,13 +245,13 @@ test "sin32.special" { test "sin64.normal" { const epsilon = math.floatEps(f64); - try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon); - try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon); - try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon); - try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon); - try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon); - try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon); - try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon); + try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon); + try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon); + try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon); + try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon); + try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon); + try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon); + try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon); } test "sin64.special" { @@ -244,13 +260,13 @@ test "sin64.special" { test "sin80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon); } test "sin80.special" { @@ -259,13 +275,13 @@ test "sin80.special" { test "sin128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon); } test "sin128.special" { @@ -274,10 +290,10 @@ test "sin128.special" { test "sin32 #9901" { const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000)); - _ = sinf(float); + _ = sin_f32(float); } test "sin64 #9901" { const float: f64 = @bitCast(@as(u64, 0b1111111101000001000000001111110111111111100000000000000000000001)); - _ = sin(float); + _ = sin_f64(float); } diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 24bb751e76e7e93d32b05a4a801dec6d5d474709..6d2b9f007a90f94c158bb636d3fcd1d8e6b40a7c 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -25,16 +25,23 @@ comptime { symbol(&sincosl, "sincosl"); } -pub fn sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.c) void { +fn sincosh(x: compiler_rt.f16.Abi, r_sin: *compiler_rt.f16.Abi, r_cos: *compiler_rt.f16.Abi) callconv(.c) void { + const s, const c = sincos_f16(compiler_rt.f16.fromAbi(x)); + r_sin.* = compiler_rt.f16.toAbi(s); + r_cos.* = compiler_rt.f16.toAbi(c); +} +pub fn sincos_f16(x: f16) struct { f16, f16 } { // TODO: more efficient implementation - var big_sin: f32 = undefined; - var big_cos: f32 = undefined; - sincosf(x, &big_sin, &big_cos); - r_sin.* = @as(f16, @floatCast(big_sin)); - r_cos.* = @as(f16, @floatCast(big_cos)); + const s, const c = sincos_f32(x); + return .{ @floatCast(s), @floatCast(c) }; } -pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { +fn sincosf(x: compiler_rt.f32.Abi, r_sin: *compiler_rt.f32.Abi, r_cos: *compiler_rt.f32.Abi) callconv(.c) void { + const s, const c = sincos_f32(compiler_rt.f32.fromAbi(x)); + r_sin.* = compiler_rt.f32.toAbi(s); + r_cos.* = compiler_rt.f32.toAbi(c); +} +pub fn sincos_f32(x: f32) struct { f32, f32 } { const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 const sc3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2 @@ -56,13 +63,9 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { mem.doNotOptimizeAway(x + 0x1p120); } } - r_sin.* = x; - r_cos.* = 1.0; - return; + return .{ x, 1.0 }; } - r_sin.* = trig.sindf(x); - r_cos.* = trig.cosdf(x); - return; + return .{ trig.sindf(x), trig.cosdf(x) }; } // |x| ~<= 5*pi/4 @@ -70,18 +73,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { // |x| ~<= 3pi/4 if (ix <= 0x4016cbe3) { if (sign) { - r_sin.* = -trig.cosdf(x + sc1pio2); - r_cos.* = trig.sindf(x + sc1pio2); + return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) }; } else { - r_sin.* = trig.cosdf(sc1pio2 - x); - r_cos.* = trig.sindf(sc1pio2 - x); + return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) }; } - return; } // -sin(x+c) is not correct if x+c could be 0: -0 vs +0 - r_sin.* = -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2); - r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2); - return; + return .{ + -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2), + -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2), + }; } // |x| ~<= 9*pi/4 @@ -89,25 +90,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { // |x| ~<= 7*pi/4 if (ix <= 0x40afeddf) { if (sign) { - r_sin.* = trig.cosdf(x + sc3pio2); - r_cos.* = -trig.sindf(x + sc3pio2); + return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) }; } else { - r_sin.* = -trig.cosdf(x - sc3pio2); - r_cos.* = trig.sindf(x - sc3pio2); + return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) }; } - return; } - r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2); - r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2); - return; + return .{ + trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2), + trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2), + }; } // sin(Inf or NaN) is NaN if (ix >= 0x7f800000) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } // general argument reduction needed @@ -115,27 +112,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { const n = rem_pio2f(x, &y); const s = trig.sindf(y); const c = trig.cosdf(y); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { +fn sincos(x: compiler_rt.f64.Abi, r_sin: *compiler_rt.f64.Abi, r_cos: *compiler_rt.f64.Abi) callconv(.c) void { + const s, const c = sincos_f64(compiler_rt.f64.fromAbi(x)); + r_sin.* = compiler_rt.f64.toAbi(s); + r_cos.* = compiler_rt.f64.toAbi(c); +} +pub fn sincos_f64(x: f64) struct { f64, f64 } { const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff; // |x| ~< pi/4 @@ -150,21 +140,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { mem.doNotOptimizeAway(x + 0x1p120); } } - r_sin.* = x; - r_cos.* = 1.0; - return; + return .{ x, 1.0 }; } - r_sin.* = trig.sin(x, 0.0, 0); - r_cos.* = trig.cos(x, 0.0); - return; + return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) }; } // sincos(Inf or NaN) is NaN if (ix >= 0x7ff00000) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } // argument reduction needed @@ -172,33 +156,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { const n = rem_pio2(x, &y); const s = trig.sin(y[0], y[1], 1); const c = trig.cos(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void { +fn sincosx(x: compiler_rt.f80.Abi, r_sin: *compiler_rt.f80.Abi, r_cos: *compiler_rt.f80.Abi) callconv(.c) void { + const s, const c = sincos_f80(compiler_rt.f80.fromAbi(x)); + r_sin.* = compiler_rt.f80.toAbi(s); + r_cos.* = compiler_rt.f80.toAbi(c); +} +pub fn sincos_f80(x: f80) struct { f80, f80 } { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } if (@abs(x) < trig.pi_4) { @@ -207,47 +182,34 @@ pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void { if (compiler_rt.want_float_exceptions and se == 0) { mem.doNotOptimizeAway(x * 0x1p-120); } - r_sin.* = x; // raise inexact if x!=0 - r_cos.* = 1.0 + x; - return; + return .{ x, 1.0 + x }; } - r_sin.* = trig.sinx(x, 0.0, 0); - r_cos.* = trig.cosx(x, 0.0); - return; + return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) }; } var y: [2]f80 = undefined; const n = rem_pio2l(f80, x, &y); const s = trig.sinx(y[0], y[1], 1); const c = trig.cosx(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } -pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { +fn sincosq(x: compiler_rt.f128.Abi, r_sin: *compiler_rt.f128.Abi, r_cos: *compiler_rt.f128.Abi) callconv(.c) void { + const s, const c = sincos_f128(compiler_rt.f128.fromAbi(x)); + r_sin.* = compiler_rt.f128.toAbi(s); + r_cos.* = compiler_rt.f128.toAbi(c); +} +pub fn sincos_f128(x: f128) struct { f128, f128 } { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { const result = x - x; - r_sin.* = result; - r_cos.* = result; - return; + return .{ result, result }; } if (@abs(x) < trig.pi_4) { @@ -256,78 +218,63 @@ pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { if (compiler_rt.want_float_exceptions and se == 0) { mem.doNotOptimizeAway(x * 0x1p-120); } - r_sin.* = x; // raise inexact if x!=0 - r_cos.* = 1.0 + x; - return; + return .{ x, 1.0 + x }; } - r_sin.* = trig.sinq(x, 0.0, 0); - r_cos.* = trig.cosq(x, 0.0); - return; + return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) }; } var y: [2]f128 = undefined; const n = rem_pio2l(f128, x, &y); const s = trig.sinq(y[0], y[1], 1); const c = trig.cosq(y[0], y[1]); - switch (n & 3) { - 0 => { - r_sin.* = s; - r_cos.* = c; - }, - 1 => { - r_sin.* = c; - r_cos.* = -s; - }, - 2 => { - r_sin.* = -s; - r_cos.* = -c; - }, - else => { - r_sin.* = -c; - r_cos.* = s; - }, - } + return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { + 0 => .{ s, c }, + 1 => .{ c, -s }, + 2 => .{ -s, -c }, + 3 => .{ -c, s }, + }; } pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void { - switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sincos(x, r_sin, r_cos), - 80 => return sincosx(x, r_sin, r_cos), - 128 => return sincosq(x, r_sin, r_cos), - else => @compileError("unreachable"), - } + r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) { + 64 => sincos_f64(x), + 80 => sincos_f80(x), + 128 => sincos_f128(x), + else => comptime unreachable, + }; } fn testSincosSpecial(comptime T: type) !void { const f = switch (T) { - f32 => sincosf, - f64 => sincos, - f80 => sincosx, - f128 => sincosq, + f16 => sincos_f16, + f32 => sincos_f32, + f64 => sincos_f64, + f80 => sincos_f80, + f128 => sincos_f128, else => @compileError("unimplemented"), }; var s: T = undefined; var c: T = undefined; - f(0.0, &s, &c); + s, c = f(0.0); try expect(math.isPositiveZero(s)); try expect(c == 1.0); - f(-0.0, &s, &c); + s, c = f(-0.0); try expect(math.isNegativeZero(s)); try expect(c == 1.0); - f(math.inf(T), &s, &c); + s, c = f(math.inf(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); - f(-math.inf(T), &s, &c); + s, c = f(-math.inf(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); - f(math.nan(T), &s, &c); + s, c = f(math.nan(T)); try expect(math.isNan(s)); try expect(math.isNan(c)); } @@ -337,31 +284,31 @@ test "sincos32.normal" { var s: f32 = undefined; var c: f32 = undefined; - sincosf(0.0, &s, &c); + s, c = sincos_f32(0.0); try expectApproxEqAbs(@as(f32, 0.0), s, epsilon); try expectApproxEqAbs(@as(f32, 1.0), c, epsilon); - sincosf(0.2, &s, &c); + s, c = sincos_f32(0.2); try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon); try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon); - sincosf(0.8923, &s, &c); + s, c = sincos_f32(0.8923); try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon); try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon); - sincosf(1.5, &s, &c); + s, c = sincos_f32(1.5); try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon); try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); - sincosf(-1.5, &s, &c); + s, c = sincos_f32(-1.5); try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon); try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); - sincosf(37.45, &s, &c); + s, c = sincos_f32(37.45); try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon); try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon); - sincosf(89.123, &s, &c); + s, c = sincos_f32(89.123); try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon); try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon); } @@ -375,31 +322,31 @@ test "sincos64.normal" { var s: f64 = undefined; var c: f64 = undefined; - sincos(0.0, &s, &c); + s, c = sincos_f64(0.0); try expectApproxEqAbs(@as(f64, 0.0), s, epsilon); try expectApproxEqAbs(@as(f64, 1.0), c, epsilon); - sincos(0.2, &s, &c); + s, c = sincos_f64(0.2); try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon); try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon); - sincos(0.8923, &s, &c); + s, c = sincos_f64(0.8923); try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon); try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon); - sincos(1.5, &s, &c); + s, c = sincos_f64(1.5); try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon); try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); - sincos(-1.5, &s, &c); + s, c = sincos_f64(-1.5); try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon); try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); - sincos(37.45, &s, &c); + s, c = sincos_f64(37.45); try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon); try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon); - sincos(89.123, &s, &c); + s, c = sincos_f64(89.123); try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon); try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon); } @@ -413,31 +360,31 @@ test "sincos80.normal" { var s: f80 = undefined; var c: f80 = undefined; - sincosx(0.0, &s, &c); + s, c = sincos_f80(0.0); try expectApproxEqAbs(@as(f80, 0.0), s, epsilon); try expectApproxEqAbs(@as(f80, 1.0), c, epsilon); - sincosx(0.2, &s, &c); + s, c = sincos_f80(0.2); try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon); try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon); - sincosx(0.8923, &s, &c); + s, c = sincos_f80(0.8923); try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon); try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon); - sincosx(1.5, &s, &c); + s, c = sincos_f80(1.5); try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); - sincosx(-1.5, &s, &c); + s, c = sincos_f80(-1.5); try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); - sincosx(37.45, &s, &c); + s, c = sincos_f80(37.45); try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon); try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon); - sincosx(89.123, &s, &c); + s, c = sincos_f80(89.123); try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon); try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon); } @@ -451,31 +398,31 @@ test "sincos128.normal" { var s: f128 = undefined; var c: f128 = undefined; - sincosq(0.0, &s, &c); + s, c = sincos_f128(0.0); try expectApproxEqAbs(@as(f128, 0.0), s, epsilon); try expectApproxEqAbs(@as(f128, 1.0), c, epsilon); - sincosq(0.2, &s, &c); + s, c = sincos_f128(0.2); try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon); try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon); - sincosq(0.8923, &s, &c); + s, c = sincos_f128(0.8923); try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon); try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon); - sincosq(1.5, &s, &c); + s, c = sincos_f128(1.5); try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); - sincosq(-1.5, &s, &c); + s, c = sincos_f128(-1.5); try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon); try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); - sincosq(37.45, &s, &c); + s, c = sincos_f128(37.45); try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon); try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon); - sincosq(89.123, &s, &c); + s, c = sincos_f128(89.123); try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon); try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon); } diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index 739285af0eaa66af2cf6ed31a3dcc142a708b590..56e43a42fcdd437811ad00d7290de45d5cee82f3 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -28,7 +28,10 @@ comptime { symbol(&sqrtl, "sqrtl"); } -pub fn __sqrth(x: f16) callconv(.c) f16 { +fn __sqrth(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(sqrt_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn sqrt_f16(x: f16) f16 { var ix: u16 = @bitCast(x); var top = ix >> 10; @@ -93,7 +96,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 { return y; } -pub fn sqrtf(x: f32) callconv(.c) f32 { +fn sqrtf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(sqrt_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn sqrt_f32(x: f32) f32 { var ix: u32 = @bitCast(x); if (ix < @as(u32, @bitCast(@as(f32, 0x1p-126))) or @as(u32, @bitCast(std.math.inf(f32))) <= ix) { @@ -147,7 +153,10 @@ pub fn sqrtf(x: f32) callconv(.c) f32 { return y + t; } -pub fn sqrt(x: f64) callconv(.c) f64 { +fn sqrt(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(sqrt_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn sqrt_f64(x: f64) f64 { var ix: u64 = @bitCast(x); var top = ix >> 52; @@ -284,7 +293,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 { return y; } -pub fn __sqrtx(x: f80) callconv(.c) f80 { +fn __sqrtx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(sqrt_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn sqrt_f80(x: f80) f80 { var ix: u80 = @bitCast(x); var top = ix >> 64; @@ -381,7 +393,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 { return y; } -pub fn sqrtq(x: f128) callconv(.c) f128 { +fn sqrtq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(sqrt_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn sqrt_f128(x: f128) f128 { var ix: u128 = @bitCast(x); var top = ix >> 112; @@ -483,10 +498,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void { pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return sqrt(x), - 80 => return __sqrtx(x), - 128 => return sqrtq(x), - else => @compileError("unreachable"), + 64 => return sqrt_f64(x), + 80 => return sqrt_f80(x), + 128 => return sqrt_f128(x), + else => comptime unreachable, } } @@ -545,187 +560,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 { return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40); } -test "__sqrth" { +test "sqrt_f16" { // sqrt(±0) is ±0 - try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(__sqrth(0x1.FFCp15), 0x1.FFCp7); + try std.testing.expectEqual(sqrt_f16(0x1.FFCp15), 0x1.FFCp7); // sqrt(4)=2 - try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0); - try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0); - try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1); + try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0); + try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(__sqrth(0x1p-14), 0x1p-7); + try std.testing.expectEqual(sqrt_f16(0x1p-14), 0x1p-7); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(__sqrth(0x0.004p-14), 0x1p-12); + try std.testing.expectEqual(sqrt_f16(0x0.004p-14), 0x1p-12); // sqrt(inf) is inf - try std.testing.expect(math.isInf(__sqrth(math.inf(f16)))); + try std.testing.expect(math.isInf(sqrt_f16(math.inf(f16)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(__sqrth(math.nan(f16)))); + try std.testing.expect(math.isNan(sqrt_f16(math.nan(f16)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(__sqrth(-0x1p-14))); - try std.testing.expect(math.isNan(__sqrth(-0x1p+0))); - try std.testing.expect(math.isNan(__sqrth(-math.inf(f16)))); + try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14))); + try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0))); + try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16)))); // random arguments - try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7); - try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6); - try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4); - try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4); - try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5); - try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4); - try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4); - try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2); - try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4); - try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6); + try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7); + try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6); + try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4); + try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4); + try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5); + try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4); + try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4); + try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2); + try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4); + try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6); } -test "sqrtf" { +test "sqrt_f32" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrtf(0x1.FFFFFEp127), 0x1.FFFFFEp63); + try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp127), 0x1.FFFFFEp63); // sqrt(4)=2 - try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0); - try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); + try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0); + try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrtf(0x1p-126), 0x1p-63); + try std.testing.expectEqual(sqrt_f32(0x1p-126), 0x1p-63); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrtf(0x0.000002p-126), 0x1.6a09e6p-75); + try std.testing.expectEqual(sqrt_f32(0x0.000002p-126), 0x1.6a09e6p-75); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrtf(math.inf(f32)))); + try std.testing.expect(math.isInf(sqrt_f32(math.inf(f32)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrtf(math.nan(f32)))); + try std.testing.expect(math.isNan(sqrt_f32(math.nan(f32)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrtf(-0x1p-149))); - try std.testing.expect(math.isNan(sqrtf(-0x1p0))); - try std.testing.expect(math.isNan(sqrtf(-math.inf(f32)))); + try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149))); + try std.testing.expect(math.isNan(sqrt_f32(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32)))); // random arguments - try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38); - try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51); - try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56); - try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9); - try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15); - try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44); - try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7); - try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24); - try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38); - try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39); + try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38); + try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51); + try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56); + try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9); + try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15); + try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44); + try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7); + try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24); + try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38); + try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39); } -test "sqrt" { +test "sqrt_f64" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrt(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511); + try std.testing.expectEqual(sqrt_f64(math.floatMax(f64)), 0x1.FFFFFFFFFFFFFp511); // sqrt(4)=2 - try std.testing.expectEqual(sqrt(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrt(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0); - try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); + try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0); + try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrt(math.floatMin(f64)), 0x1p-511); + try std.testing.expectEqual(sqrt_f64(math.floatMin(f64)), 0x1p-511); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrt(math.floatTrueMin(f64)), 0x1p-537); + try std.testing.expectEqual(sqrt_f64(math.floatTrueMin(f64)), 0x1p-537); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrt(math.inf(f64)))); + try std.testing.expect(math.isInf(sqrt_f64(math.inf(f64)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrt(math.nan(f64)))); + try std.testing.expect(math.isNan(sqrt_f64(math.nan(f64)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrt(-0x1p-1074))); - try std.testing.expect(math.isNan(sqrt(-0x1p0))); - try std.testing.expect(math.isNan(sqrt(-math.inf(f64)))); + try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074))); + try std.testing.expect(math.isNan(sqrt_f64(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64)))); // random arguments - try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); - try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); - try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); - try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); - try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); - try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); - try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); - try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); - try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); - try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); + try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); + try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); + try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); + try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); + try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); + try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); + try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); + try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); + try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); + try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); } test "__sqrtx" { // sqrt(±0) is ±0 - try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(__sqrtx(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191); + try std.testing.expectEqual(sqrt_f80(math.floatMax(f80)), 0x1.FFFFFFFFFFFFFFFEp8191); // sqrt(4)=2 - try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0); - try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0); - try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); + try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0); + try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(__sqrtx(math.floatMin(f80)), 0x1p-8191); + try std.testing.expectEqual(sqrt_f80(math.floatMin(f80)), 0x1p-8191); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(__sqrtx(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223); + try std.testing.expectEqual(sqrt_f80(math.floatTrueMin(f80)), 0x1.6A09E667F3BCC908p-8223); // sqrt(inf) is inf - try std.testing.expect(math.isInf(__sqrtx(math.inf(f80)))); + try std.testing.expect(math.isInf(sqrt_f80(math.inf(f80)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(__sqrtx(math.nan(f80)))); + try std.testing.expect(math.isNan(sqrt_f80(math.nan(f80)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442))); - try std.testing.expect(math.isNan(__sqrtx(-0x1p0))); - try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80)))); + try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442))); + try std.testing.expect(math.isNan(sqrt_f80(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80)))); // random arguments - try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); - try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); - try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); - try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); - try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); - try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); - try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); - try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); - try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); - try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); + try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); + try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); + try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); + try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); + try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); + try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); + try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); + try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); + try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); + try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); } -test "sqrtq" { +test "sqrt_f128" { // sqrt(±0) is ±0 - try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0); - try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0); + try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0); + try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0); // sqrt(+max) is finite - try std.testing.expectEqual(sqrtq(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191); + try std.testing.expectEqual(sqrt_f128(math.floatMax(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp8191); // sqrt(4)=2 - try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1); + try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1); // sqrt(x) for x=1, 1±ulp - try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0); - try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0); - try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); + try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0); + try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0); + try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); // sqrt(+min) is non-zero - try std.testing.expectEqual(sqrtq(math.floatMin(f128)), 0x1p-8191); + try std.testing.expectEqual(sqrt_f128(math.floatMin(f128)), 0x1p-8191); // sqrt(min subnormal) is non-zero - try std.testing.expectEqual(sqrtq(math.floatTrueMin(f128)), 0x1p-8247); + try std.testing.expectEqual(sqrt_f128(math.floatTrueMin(f128)), 0x1p-8247); // sqrt(inf) is inf - try std.testing.expect(math.isInf(sqrtq(math.inf(f128)))); + try std.testing.expect(math.isInf(sqrt_f128(math.inf(f128)))); // sqrt(nan) is nan - try std.testing.expect(math.isNan(sqrtq(math.nan(f128)))); + try std.testing.expect(math.isNan(sqrt_f128(math.nan(f128)))); // sqrt(-ve) is nan - try std.testing.expect(math.isNan(sqrtq(-0x1p-16442))); - try std.testing.expect(math.isNan(sqrtq(-0x1p0))); - try std.testing.expect(math.isNan(sqrtq(-math.inf(f128)))); + try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442))); + try std.testing.expect(math.isNan(sqrt_f128(-0x1p0))); + try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128)))); // random arguments - try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); - try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); - try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); - try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); - try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); - try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); - try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); - try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); - try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); - try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); + try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); + try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); + try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); + try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); + try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); + try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); + try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); + try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); + try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); + try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); } diff --git a/lib/compiler_rt/subdf3.zig b/lib/compiler_rt/subdf3.zig deleted file mode 100644 index 4d00a7f03ae71c4f9bf2ffecbcd1123216dff6b6..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subdf3.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const addf3 = @import("./addf3.zig").addf3; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dsub, "__aeabi_dsub"); - } else { - symbol(&__subdf3, "__subdf3"); - } -} - -fn __subdf3(a: f64, b: f64) callconv(.c) f64 { - return sub(a, b); -} - -fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { - return sub(a, b); -} - -inline fn sub(a: f64, b: f64) f64 { - const neg_b = @as(f64, @bitCast(@as(u64, @bitCast(b)) ^ (@as(u64, 1) << 63))); - return addf3(f64, a, neg_b); -} diff --git a/lib/compiler_rt/subhf3.zig b/lib/compiler_rt/subhf3.zig deleted file mode 100644 index 258401d2957a6d3aafcd0aa02c6de63ca0211952..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subhf3.zig +++ /dev/null @@ -1,12 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - symbol(&__subhf3, "__subhf3"); -} - -fn __subhf3(a: f16, b: f16) callconv(.c) f16 { - const neg_b = @as(f16, @bitCast(@as(u16, @bitCast(b)) ^ (@as(u16, 1) << 15))); - return addf3(f16, a, neg_b); -} diff --git a/lib/compiler_rt/subsf3.zig b/lib/compiler_rt/subsf3.zig deleted file mode 100644 index 94d47220166aff38656455d3f50fa2b061df3f61..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subsf3.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_fsub, "__aeabi_fsub"); - } else { - symbol(&__subsf3, "__subsf3"); - } -} - -fn __subsf3(a: f32, b: f32) callconv(.c) f32 { - return sub(a, b); -} - -fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { - return sub(a, b); -} - -inline fn sub(a: f32, b: f32) f32 { - const neg_b = @as(f32, @bitCast(@as(u32, @bitCast(b)) ^ (@as(u32, 1) << 31))); - return addf3(f32, a, neg_b); -} diff --git a/lib/compiler_rt/subtf3.zig b/lib/compiler_rt/subtf3.zig deleted file mode 100644 index 46580f1728d70b85c83259dce39cb860e46ac10e..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subtf3.zig +++ /dev/null @@ -1,27 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const addf3 = @import("./addf3.zig").addf3; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__subtf3, "__subkf3"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_sub, "_Qp_sub"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__subtf3, "_Q_sub"); - } - symbol(&__subtf3, "__subtf3"); -} - -pub fn __subtf3(a: f128, b: f128) callconv(.c) f128 { - return sub(a, b); -} - -fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { - c.* = sub(a.*, b.*); -} - -inline fn sub(a: f128, b: f128) f128 { - const neg_b = @as(f128, @bitCast(@as(u128, @bitCast(b)) ^ (@as(u128, 1) << 127))); - return addf3(f128, a, neg_b); -} diff --git a/lib/compiler_rt/subvdi3.zig b/lib/compiler_rt/subvdi3.zig index 62bb1b406835c1a72588cd9c1d08705f6663bbd2..2fedc77ee2c07fe42ded5f5da11191a41fc17a0f 100644 --- a/lib/compiler_rt/subvdi3.zig +++ b/lib/compiler_rt/subvdi3.zig @@ -1,5 +1,6 @@ -const symbol = @import("../compiler_rt.zig").symbol; const testing = @import("std").testing; +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; comptime { symbol(&__subvdi3, "__subvdi3"); @@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 { const sum = a -% b; // Overflow occurred iff the operands have opposite signs, and the sign of the // sum is the opposite of the lhs sign. - if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow"); + if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/subvsi3.zig b/lib/compiler_rt/subvsi3.zig index 0744585770237d034f35947a927155efe23eaef9..0d2a47e7cbfa8beb25cbeedc1809e549481db97e 100644 --- a/lib/compiler_rt/subvsi3.zig +++ b/lib/compiler_rt/subvsi3.zig @@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 { const sum = a -% b; // Overflow occurred iff the operands have opposite signs, and the sign of the // sum is the opposite of the lhs sign. - if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow"); + if (((a ^ b) & (sum ^ a)) < 0) @panic("integer overflow"); return sum; } diff --git a/lib/compiler_rt/subxf3.zig b/lib/compiler_rt/subxf3.zig deleted file mode 100644 index 1c2dcd65429596c975937432aae6eaefb89c2f72..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/subxf3.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__subxf3, "__subxf3"); -} - -fn __subxf3(a: f80, b: f80) callconv(.c) f80 { - var b_rep = std.math.F80.fromFloat(b); - b_rep.exp ^= 0x8000; - const neg_b = b_rep.toFloat(); - return a + neg_b; -} diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 6cbc3cb098acd1f6a719451d103574b935a8bb2c..038ac85b6dc2dd9e7d742936bd0df3095dc4b9ec 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -21,13 +21,13 @@ const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; const arch = builtin.cpu.arch; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; comptime { - symbol(&tanh, "__tanh"); + symbol(&__tanh, "__tanh"); symbol(&tanf, "tanf"); symbol(&tan, "tan"); - symbol(&tanx, "__tanx"); + symbol(&__tanx, "__tanx"); if (compiler_rt.want_ppc_abi) { symbol(&tanq, "tanf128"); } @@ -35,12 +35,18 @@ comptime { symbol(&tanl, "tanl"); } -pub fn tanh(x: f16) callconv(.c) f16 { +fn __tanh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(tan_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn tan_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(tanf(x)); + return @floatCast(tan_f32(x)); } -pub fn tanf(x: f32) callconv(.c) f32 { +fn tanf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(tan_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn tan_f32(x: f32) f32 { // Small multiples of pi/2 rounded to double precision. const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 @@ -90,7 +96,10 @@ pub fn tanf(x: f32) callconv(.c) f32 { return kernel.tandf(y, n & 1 != 0); } -pub fn tan(x: f64) callconv(.c) f64 { +fn tan(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(tan_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn tan_f64(x: f64) f64 { var ix = @as(u64, @bitCast(x)) >> 32; ix &= 0x7fffffff; @@ -120,7 +129,10 @@ pub fn tan(x: f64) callconv(.c) f64 { return kernel.tan(y[0], y[1], n & 1 != 0); } -pub fn tanx(x: f80) callconv(.c) f80 { +fn __tanx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(tan_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn tan_f80(x: f80) f80 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -141,7 +153,10 @@ pub fn tanx(x: f80) callconv(.c) f80 { return kernel.tanx(y[0], y[1], n & 1); } -pub fn tanq(x: f128) callconv(.c) f128 { +fn tanq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(tan_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn tan_f128(x: f128) f128 { const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; @@ -164,18 +179,21 @@ pub fn tanq(x: f128) callconv(.c) f128 { pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return tan(x), - 80 => return tanx(x), - 128 => return tanq(x), - else => @compileError("unreachable"), + 64 => return tan_f64(x), + 80 => return tan_f80(x), + 128 => return tan_f128(x), + else => comptime unreachable, } } fn testTanNormal(comptime T: type) !void { const f = switch (T) { - f32 => tanf, - f64 => tan, - else => @compileError("unimplemented"), + f16 => tan_f16, + f32 => tan_f32, + f64 => tan_f64, + f80 => tan_f80, + f128 => tan_f128, + else => comptime unreachable, }; const epsilon = 0.00001; @@ -189,11 +207,12 @@ fn testTanNormal(comptime T: type) !void { fn testTanSpecial(comptime T: type) !void { const f = switch (T) { - f32 => tanf, - f64 => tan, - f80 => tanx, - f128 => tanq, - else => @compileError("unimplemented"), + f16 => tan_f16, + f32 => tan_f32, + f64 => tan_f64, + f80 => tan_f80, + f128 => tan_f128, + else => comptime unreachable, }; try expect(math.isPositiveZero(f(0.0))); @@ -214,23 +233,23 @@ test "tan64.normal" { test "tan80.normal" { const epsilon = math.floatEps(f80); - try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon); - try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon); - try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon); - try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon); - try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon); - try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon); + try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon); + try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon); + try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon); + try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon); + try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon); + try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon); } test "tan128.normal" { const epsilon = math.floatEps(f128); - try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon); - try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon); - try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon); - try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon); - try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon); - try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon); + try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon); + try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon); + try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon); + try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon); + try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon); + try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon); } test "tan32.special" { diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index aa2eb560dfd8035f14aa07c8e51c5c117daad042..0653178b54b50256e43168d377f59377f34dcc14 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -24,12 +24,18 @@ comptime { symbol(&truncl, "truncl"); } -pub fn __trunch(x: f16) callconv(.c) f16 { +fn __trunch(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { + return compiler_rt.f16.toAbi(trunc_f16(compiler_rt.f16.fromAbi(x))); +} +pub fn trunc_f16(x: f16) f16 { // TODO: more efficient implementation - return @floatCast(truncf(x)); + return @floatCast(trunc_f32(x)); } -pub fn truncf(x: f32) callconv(.c) f32 { +fn truncf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(trunc_f32(compiler_rt.f32.fromAbi(x))); +} +pub fn trunc_f32(x: f32) f32 { const u: u32 = @bitCast(x); var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9; var m: u32 = undefined; @@ -50,7 +56,10 @@ pub fn truncf(x: f32) callconv(.c) f32 { } } -pub fn trunc(x: f64) callconv(.c) f64 { +fn trunc(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(trunc_f64(compiler_rt.f64.fromAbi(x))); +} +pub fn trunc_f64(x: f64) f64 { const u: u64 = @bitCast(x); var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12; var m: u64 = undefined; @@ -71,12 +80,18 @@ pub fn trunc(x: f64) callconv(.c) f64 { } } -pub fn __truncx(x: f80) callconv(.c) f80 { +fn __truncx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(trunc_f80(compiler_rt.f80.fromAbi(x))); +} +pub fn trunc_f80(x: f80) f80 { // TODO: more efficient implementation - return @floatCast(truncq(x)); + return @floatCast(trunc_f128(x)); } -pub fn truncq(x: f128) callconv(.c) f128 { +fn truncq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { + return compiler_rt.f128.toAbi(trunc_f128(compiler_rt.f128.fromAbi(x))); +} +pub fn trunc_f128(x: f128) f128 { const u: u128 = @bitCast(x); var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16; var m: u128 = undefined; @@ -99,51 +114,69 @@ pub fn truncq(x: f128) callconv(.c) f128 { pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble { switch (@typeInfo(c_longdouble).float.bits) { - 64 => return trunc(x), - 80 => return __truncx(x), - 128 => return truncq(x), - else => @compileError("unreachable"), + 64 => return trunc_f64(x), + 80 => return trunc_f80(x), + 128 => return trunc_f128(x), + else => comptime unreachable, } } -test "trunc32" { - try expect(truncf(1.3) == 1.0); - try expect(truncf(-1.3) == -1.0); - try expect(truncf(0.2) == 0.0); +test trunc_f16 { + try expect(trunc_f16(1.3) == 1.0); + try expect(trunc_f16(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f16(0.2))); + try expect(math.isNegativeZero(trunc_f16(-0.2))); + try expect(math.isPositiveZero(trunc_f16(0.0))); + try expect(math.isNegativeZero(trunc_f16(-0.0))); + try expect(math.isPositiveInf(trunc_f16(math.inf(f32)))); + try expect(math.isNegativeInf(trunc_f16(-math.inf(f32)))); + try expect(math.isNan(trunc_f16(math.nan(f32)))); } -test "trunc64" { - try expect(trunc(1.3) == 1.0); - try expect(trunc(-1.3) == -1.0); - try expect(trunc(0.2) == 0.0); +test trunc_f32 { + try expect(trunc_f32(1.3) == 1.0); + try expect(trunc_f32(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f32(0.2))); + try expect(math.isNegativeZero(trunc_f32(-0.2))); + try expect(math.isPositiveZero(trunc_f32(0.0))); + try expect(math.isNegativeZero(trunc_f32(-0.0))); + try expect(math.isPositiveInf(trunc_f32(math.inf(f32)))); + try expect(math.isNegativeInf(trunc_f32(-math.inf(f32)))); + try expect(math.isNan(trunc_f32(math.nan(f32)))); } -test "trunc128" { - try expect(truncq(1.3) == 1.0); - try expect(truncq(-1.3) == -1.0); - try expect(truncq(0.2) == 0.0); +test trunc_f64 { + try expect(trunc_f64(1.3) == 1.0); + try expect(trunc_f64(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f64(0.2))); + try expect(math.isNegativeZero(trunc_f64(-0.2))); + try expect(math.isPositiveZero(trunc_f64(0.0))); + try expect(math.isNegativeZero(trunc_f64(-0.0))); + try expect(math.isPositiveInf(trunc_f64(math.inf(f64)))); + try expect(math.isNegativeInf(trunc_f64(-math.inf(f64)))); + try expect(math.isNan(trunc_f64(math.nan(f64)))); } -test "trunc32.special" { - try expect(truncf(0.0) == 0.0); // 0x3F800000 - try expect(truncf(-0.0) == -0.0); - try expect(math.isPositiveInf(truncf(math.inf(f32)))); - try expect(math.isNegativeInf(truncf(-math.inf(f32)))); - try expect(math.isNan(truncf(math.nan(f32)))); +test trunc_f80 { + try expect(trunc_f80(1.3) == 1.0); + try expect(trunc_f80(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f80(0.2))); + try expect(math.isNegativeZero(trunc_f80(-0.2))); + try expect(math.isPositiveZero(trunc_f80(0.0))); + try expect(math.isNegativeZero(trunc_f80(-0.0))); + try expect(math.isPositiveInf(trunc_f80(math.inf(f64)))); + try expect(math.isNegativeInf(trunc_f80(-math.inf(f64)))); + try expect(math.isNan(trunc_f80(math.nan(f64)))); } -test "trunc64.special" { - try expect(trunc(0.0) == 0.0); - try expect(trunc(-0.0) == -0.0); - try expect(math.isPositiveInf(trunc(math.inf(f64)))); - try expect(math.isNegativeInf(trunc(-math.inf(f64)))); - try expect(math.isNan(trunc(math.nan(f64)))); -} - -test "trunc128.special" { - try expect(truncq(0.0) == 0.0); - try expect(truncq(-0.0) == -0.0); - try expect(math.isPositiveInf(truncq(math.inf(f128)))); - try expect(math.isNegativeInf(truncq(-math.inf(f128)))); - try expect(math.isNan(truncq(math.nan(f128)))); +test trunc_f128 { + try expect(trunc_f128(1.3) == 1.0); + try expect(trunc_f128(-1.3) == -1.0); + try expect(math.isPositiveZero(trunc_f128(0.2))); + try expect(math.isNegativeZero(trunc_f128(-0.2))); + try expect(math.isPositiveZero(trunc_f128(0.0))); + try expect(math.isNegativeZero(trunc_f128(-0.0))); + try expect(math.isPositiveInf(trunc_f128(math.inf(f128)))); + try expect(math.isNegativeInf(trunc_f128(-math.inf(f128)))); + try expect(math.isNan(trunc_f128(math.nan(f128)))); } diff --git a/lib/compiler_rt/truncdfhf2.zig b/lib/compiler_rt/truncdfhf2.zig deleted file mode 100644 index e01e1877633eee7077c64ef42e6cde56a0a17aee..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncdfhf2.zig +++ /dev/null @@ -1,18 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const truncf = @import("./truncf.zig").truncf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2h, "__aeabi_d2h"); - } - symbol(&__truncdfhf2, "__truncdfhf2"); -} - -pub fn __truncdfhf2(a: f64) callconv(.c) compiler_rt.F16T(f64) { - return @bitCast(truncf(f16, f64, a)); -} - -fn __aeabi_d2h(a: f64) callconv(.{ .arm_aapcs = .{} }) u16 { - return @bitCast(truncf(f16, f64, a)); -} diff --git a/lib/compiler_rt/truncdfsf2.zig b/lib/compiler_rt/truncdfsf2.zig deleted file mode 100644 index f1bada18449130344f213ad0f8272794d38f23bf..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncdfsf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_d2f, "__aeabi_d2f"); - } else { - symbol(&__truncdfsf2, "__truncdfsf2"); - } -} - -pub fn __truncdfsf2(a: f64) callconv(.c) f32 { - return truncf(f32, f64, a); -} - -fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 { - return truncf(f32, f64, a); -} diff --git a/lib/compiler_rt/truncf.zig b/lib/compiler_rt/truncf.zig index a03f3b67113028ba8a69c4fc72023b9d26f87e23..9a1cb491e27bc214a2c5c7a4a91f8f236efae1ef 100644 --- a/lib/compiler_rt/truncf.zig +++ b/lib/compiler_rt/truncf.zig @@ -1,6 +1,204 @@ const std = @import("std"); -pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { +const compiler_rt = @import("../compiler_rt.zig"); +const symbol = compiler_rt.symbol; + +comptime { + if (compiler_rt.want_aeabi) { + if (compiler_rt.gnu_f16_abi) { + symbol(&__aeabi_f2h, "__gnu_f2h_ieee"); + } else { + symbol(&__aeabi_f2h, "__aeabi_f2h"); + } + symbol(&__aeabi_d2h, "__aeabi_d2h"); + } else if (compiler_rt.gnu_f16_abi) { + symbol(&__truncsfhf2, "__gnu_f2h_ieee"); + } + symbol(&__truncsfhf2, "__truncsfhf2"); + symbol(&__truncdfhf2, "__truncdfhf2"); + symbol(&__truncxfhf2, "__truncxfhf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfhf2, "__trunckfhf2"); + } else { + symbol(&__trunctfhf2, "__trunctfhf2"); + } + + if (compiler_rt.want_aeabi) { + symbol(&__aeabi_d2f, "__aeabi_d2f"); + } else { + symbol(&__truncdfsf2, "__truncdfsf2"); + } + symbol(&__truncxfsf2, "__truncxfsf2"); + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfsf2, "__trunckfsf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtos, "_Qp_qtos"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__trunctfsf2, "_Q_qtos"); + } else { + symbol(&__trunctfsf2, "__trunctfsf2"); + } + + symbol(&__truncxfdf2, "__truncxfdf2"); + + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfdf2, "__trunckfdf2"); + } else if (compiler_rt.want_sparc64_abi) { + symbol(&_Qp_qtod, "_Qp_qtod"); + } else if (compiler_rt.want_sparc32_abi) { + symbol(&__trunctfdf2, "_Q_qtod"); + } else { + symbol(&__trunctfdf2, "__trunctfdf2"); + } + + if (compiler_rt.want_ppc_abi) { + symbol(&__trunctfxf2, "__trunckfxf2"); + } else { + symbol(&__trunctfxf2, "__trunctfxf2"); + } +} + +fn __truncsfhf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f16Conv(f32).Abi { + return compiler_rt.f16Conv(f32).toAbi(f16_floatCast_f32(compiler_rt.f32.fromAbi(a))); +} +fn __aeabi_f2h(a: u32) callconv(.{ .arm_aapcs = .{} }) u16 { + return @bitCast(f16_floatCast_f32(@bitCast(a))); +} +pub fn f16_floatCast_f32(a: f32) f16 { + return truncf(f16, f32, a); +} + +fn __truncdfhf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f16Conv(f64).Abi { + return compiler_rt.f16Conv(f64).toAbi(f16_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn __aeabi_d2h(a: u64) callconv(.{ .arm_aapcs = .{} }) u16 { + return @bitCast(f16_floatCast_f64(@bitCast(a))); +} +pub fn f16_floatCast_f64(a: f64) f16 { + return truncf(f16, f64, a); +} + +fn __truncxfhf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f16Conv(f80).Abi { + return compiler_rt.f16Conv(f80).toAbi(f16_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f16_floatCast_f80(a: f80) f16 { + return trunc_f80(f16, a); +} + +fn __trunctfhf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f16Conv(f128).Abi { + return compiler_rt.f16Conv(f128).toAbi(f16_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn f16_floatCast_f128(a: f128) f16 { + return truncf(f16, f128, a); +} + +fn __truncdfsf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f64(compiler_rt.f64.fromAbi(a))); +} +fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 { + return f32_floatCast_f64(a); +} +pub fn f32_floatCast_f64(a: f64) f32 { + return truncf(f32, f64, a); +} + +fn __truncxfsf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f32_floatCast_f80(a: f80) f32 { + return trunc_f80(f32, a); +} + +fn __trunctfsf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f32.Abi { + return compiler_rt.f32.toAbi(f32_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +fn _Qp_qtos(a: *const f128) callconv(.c) f32 { + return f32_floatCast_f128(a.*); +} +pub fn f32_floatCast_f128(a: f128) f32 { + return truncf(f32, f128, a); +} + +fn __truncxfdf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f80(compiler_rt.f80.fromAbi(a))); +} +pub fn f64_floatCast_f80(a: f80) f64 { + return trunc_f80(f64, a); +} + +fn __trunctfdf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f64.Abi { + return compiler_rt.f64.toAbi(f64_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +fn _Qp_qtod(a: *const f128) callconv(.c) f64 { + return f64_floatCast_f128(a.*); +} +pub fn f64_floatCast_f128(a: f128) f64 { + return truncf(f64, f128, a); +} + +fn __trunctfxf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f80.Abi { + return compiler_rt.f80.toAbi(f80_floatCast_f128(compiler_rt.f128.fromAbi(a))); +} +pub fn f80_floatCast_f128(a: f128) f80 { + const src_sig_bits = std.math.floatMantissaBits(f128); + const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit + + // Various constants whose values follow from the type parameters. + // Any reasonable optimizer will fold and propagate all of these. + const src_bits = @typeInfo(f128).float.bits; + const src_exp_bits = src_bits - src_sig_bits - 1; + const src_inf_exp = 0x7FFF; + + const src_inf = src_inf_exp << src_sig_bits; + const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); + const src_abs_mask = src_sign_mask - 1; + const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; + const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); + + // Break a into a sign and representation of the absolute value + const a_rep: u128 = @bitCast(a); + const a_abs = a_rep & src_abs_mask; + const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; + const integer_bit = 1 << 63; + + var res: std.math.F80 = undefined; + + if (a_abs > src_inf) { + // a is NaN. + // Conjure the result by beginning with infinity, setting the qNaN + // bit and inserting the (truncated) trailing NaN field. + res.exp = 0x7fff; + res.fraction = 0x8000000000000000; + res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))); + } else { + // The exponent of a is within the range of normal numbers in the + // destination format. We can convert by simply right-shifting with + // rounding, adding the explicit integer bit, and adjusting the exponent + res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit; + res.exp = @truncate(a_abs >> src_sig_bits); + + const round_bits = a_abs & round_mask; + if (round_bits > halfway) { + // Round to nearest + const ov = @addWithOverflow(res.fraction, 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry + } else if (round_bits == halfway) { + // Ties to even + const ov = @addWithOverflow(res.fraction, res.fraction & 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry + } + if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals + } + + res.exp |= sign; + return res.toFloat(); +} + +inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); @@ -99,7 +297,7 @@ pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t return @bitCast(result); } -pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { +inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit const dst_sig_bits = std.math.floatMantissaBits(dst_t); diff --git a/lib/compiler_rt/truncf_test.zig b/lib/compiler_rt/truncf_test.zig index 8da6fe0a19456e9898f32ea4dec4c7b8ccb221b4..6595c47b52d8f868d019c1728ae3d57735e12323 100644 --- a/lib/compiler_rt/truncf_test.zig +++ b/lib/compiler_rt/truncf_test.zig @@ -1,79 +1,82 @@ const std = @import("std"); const testing = std.testing; -const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2; -const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2; -const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2; -const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2; -const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2; -const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2; -const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2; - -fn test__truncsfhf2(a: u32, expected: u16) !void { - const actual: u16 = @bitCast(__truncsfhf2(@bitCast(a))); - - if (actual == expected) { - return; - } - - return error.TestFailure; +const impl = @import("truncf.zig"); + +const f16_floatCast_f32 = impl.f16_floatCast_f32; +const f16_floatCast_f64 = impl.f16_floatCast_f64; +const f16_floatCast_f80 = impl.f16_floatCast_f80; +const f16_floatCast_f128 = impl.f16_floatCast_f128; + +const f32_floatCast_f64 = impl.f32_floatCast_f64; +const f32_floatCast_f80 = impl.f32_floatCast_f80; +const f32_floatCast_f128 = impl.f32_floatCast_f128; + +const f64_floatCast_f80 = impl.f64_floatCast_f80; +const f64_floatCast_f128 = impl.f64_floatCast_f128; + +const f80_floatCast_f128 = impl.f80_floatCast_f128; + +fn test_f16_floatCast_f32(a: u32, expected: u16) !void { + const actual: u16 = @bitCast(f16_floatCast_f32(@bitCast(a))); + try testing.expect(actual == expected); } -test "truncsfhf2" { - try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN - try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN +test f16_floatCast_f32 { + try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN + try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN - try test__truncsfhf2(0, 0); // 0 - try test__truncsfhf2(0x80000000, 0x8000); // -0 + try test_f16_floatCast_f32(0, 0); // 0 + try test_f16_floatCast_f32(0x80000000, 0x8000); // -0 - try test__truncsfhf2(0x7f800000, 0x7c00); // inf - try test__truncsfhf2(0xff800000, 0xfc00); // -inf + try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf + try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf - try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf - try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf + try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf + try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf - try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf - try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf + try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf + try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf - try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 - try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 + try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14 + try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14 - try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 - try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 + try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504 + try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504 - try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 - try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 + try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504 + try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 - try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 - try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 + try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504 + try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 - try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 - try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 + try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10 + try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10 - try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 - try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 + try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3 + try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3 - try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 - try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 + try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535 + try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535 - try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 + try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 - try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 - try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 + try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1 + try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14 - try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 - try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 + try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24 + try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24 - try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 - try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 + try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 + try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 - try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 - try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 - try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero + try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20 + try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 + try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero } -fn test__truncdfhf2(a: f64, expected: u16) void { - const rep: u16 = @bitCast(__truncdfhf2(a)); +fn test_f16_floatCast_f64(a: f64, expected: u16) !void { + const rep: u16 = @bitCast(f16_floatCast_f64(a)); if (rep == expected) { return; @@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void { return; } } - - @panic("__truncdfhf2 test failure"); + return error.TestFailure; } -fn test__truncdfhf2_raw(a: u64, expected: u16) void { - const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a))); - - if (actual == expected) { - return; - } - - @panic("__truncdfhf2 test failure"); +fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void { + const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a))); + try testing.expect(actual == expected); } -test "truncdfhf2" { - test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN - test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN +test f16_floatCast_f64 { + try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN + try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN - test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf - test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf + try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf + try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf - test__truncdfhf2(0.0, 0x0); // zero - test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero + try test_f16_floatCast_f64(0.0, 0x0); // zero + try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero - test__truncdfhf2(3.1415926535, 0x4248); - test__truncdfhf2(-3.1415926535, 0xc248); + try test_f16_floatCast_f64(3.1415926535, 0x4248); + try test_f16_floatCast_f64(-3.1415926535, 0xc248); - test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); - test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); - test__truncdfhf2(0x1.0p+0, 0x3c00); - test__truncdfhf2(0x1.0p-14, 0x0400); + try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00); + try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62); + try test_f16_floatCast_f64(0x1.0p+0, 0x3c00); + try test_f16_floatCast_f64(0x1.0p-14, 0x0400); // denormal - test__truncdfhf2(0x1.0p-20, 0x0010); - test__truncdfhf2(0x1.0p-24, 0x0001); - test__truncdfhf2(-0x1.0p-24, 0x8001); - test__truncdfhf2(0x1.5p-25, 0x0001); + try test_f16_floatCast_f64(0x1.0p-20, 0x0010); + try test_f16_floatCast_f64(0x1.0p-24, 0x0001); + try test_f16_floatCast_f64(-0x1.0p-24, 0x8001); + try test_f16_floatCast_f64(0x1.5p-25, 0x0001); // and back to zero - test__truncdfhf2(0x1.0p-25, 0x0000); - test__truncdfhf2(-0x1.0p-25, 0x8000); + try test_f16_floatCast_f64(0x1.0p-25, 0x0000); + try test_f16_floatCast_f64(-0x1.0p-25, 0x8000); // max (precise) - test__truncdfhf2(65504.0, 0x7bff); + try test_f16_floatCast_f64(65504.0, 0x7bff); // max (rounded) - test__truncdfhf2(65519.0, 0x7bff); + try test_f16_floatCast_f64(65519.0, 0x7bff); // max (to +inf) - test__truncdfhf2(65520.0, 0x7c00); - test__truncdfhf2(-65520.0, 0xfc00); - test__truncdfhf2(65536.0, 0x7c00); + try test_f16_floatCast_f64(65520.0, 0x7c00); + try test_f16_floatCast_f64(-65520.0, 0xfc00); + try test_f16_floatCast_f64(65536.0, 0x7c00); } -fn test__trunctfsf2(a: f128, expected: u32) void { - const x = __trunctfsf2(a); +fn test_f32_floatCast_f128(a: f128, expected: u32) !void { + const x = f32_floatCast_f128(a); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void { return; } } - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "trunctfsf2" { +test f32_floatCast_f128 { // qnan - test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); + try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); // nan - test__trunctfsf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); + try test_f32_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); // inf - test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); + try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); // zero - test__trunctfsf2(0.0, 0x0); + try test_f32_floatCast_f128(0.0, 0x0); - test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); - test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); - test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); - test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); + try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); + try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); + try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); + try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); } -fn test__trunctfdf2(a: f128, expected: u64) void { - const x = __trunctfdf2(a); +fn test_f64_floatCast_f128(a: f128, expected: u64) !void { + const x = f64_floatCast_f128(a); const rep: u64 = @bitCast(x); if (rep == expected) { @@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void { return; } } - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "trunctfdf2" { +test f64_floatCast_f128 { // qnan - test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); // nan - test__trunctfdf2(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); // inf - test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); + try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); // zero - test__trunctfdf2(0.0, 0x0); + try test_f64_floatCast_f128(0.0, 0x0); - test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); - test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); - test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); - test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); + try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); + try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); + try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); + try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); } -fn test__truncdfsf2(a: f64, expected: u32) void { - const x = __truncdfsf2(a); +fn test_f32_floatCast_f64(a: f64, expected: u32) !void { + const x = f32_floatCast_f64(a); const rep: u32 = @bitCast(x); if (rep == expected) { @@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void { return; } } - - std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); - - @panic("__trunctfsf2 test failure"); + return error.TestFailure; } -test "truncdfsf2" { +test f32_floatCast_f64 { // nan & qnan - test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); - test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); // inf - test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); - test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); + try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); - test__truncdfsf2(0.0, 0x0); - test__truncdfsf2(1.0, 0x3f800000); - test__truncdfsf2(-1.0, 0xbf800000); + try test_f32_floatCast_f64(0.0, 0x0); + try test_f32_floatCast_f64(1.0, 0x3f800000); + try test_f32_floatCast_f64(-1.0, 0xbf800000); // huge number becomes inf - test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000); + try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000); } -fn test__trunctfhf2(a: f128, expected: u16) void { - const x = __trunctfhf2(a); +fn test_f16_floatCast_f128(a: f128, expected: u16) !void { + const x = f16_floatCast_f128(a); const rep: u16 = @bitCast(x); - if (rep == expected) { - return; - } - - std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); - - @panic("__trunctfhf2 test failure"); + try testing.expect(rep == expected); } -test "trunctfhf2" { +test f16_floatCast_f128 { // qNaN - test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); // NaN - test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); // inf - test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); - test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); + try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); + try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); // zero - test__trunctfhf2(0.0, 0x0); - test__trunctfhf2(-0.0, 0x8000); + try test_f16_floatCast_f128(0.0, 0x0); + try test_f16_floatCast_f128(-0.0, 0x8000); - test__trunctfhf2(3.1415926535, 0x4248); - test__trunctfhf2(-3.1415926535, 0xc248); - test__trunctfhf2(0x1.987124876876324p+100, 0x7c00); - test__trunctfhf2(0x1.987124876876324p+12, 0x6e62); - test__trunctfhf2(0x1.0p+0, 0x3c00); - test__trunctfhf2(0x1.0p-14, 0x0400); + try test_f16_floatCast_f128(3.1415926535, 0x4248); + try test_f16_floatCast_f128(-3.1415926535, 0xc248); + try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00); + try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62); + try test_f16_floatCast_f128(0x1.0p+0, 0x3c00); + try test_f16_floatCast_f128(0x1.0p-14, 0x0400); // denormal - test__trunctfhf2(0x1.0p-20, 0x0010); - test__trunctfhf2(0x1.0p-24, 0x0001); - test__trunctfhf2(-0x1.0p-24, 0x8001); - test__trunctfhf2(0x1.5p-25, 0x0001); + try test_f16_floatCast_f128(0x1.0p-20, 0x0010); + try test_f16_floatCast_f128(0x1.0p-24, 0x0001); + try test_f16_floatCast_f128(-0x1.0p-24, 0x8001); + try test_f16_floatCast_f128(0x1.5p-25, 0x0001); // and back to zero - test__trunctfhf2(0x1.0p-25, 0x0000); - test__trunctfhf2(-0x1.0p-25, 0x8000); + try test_f16_floatCast_f128(0x1.0p-25, 0x0000); + try test_f16_floatCast_f128(-0x1.0p-25, 0x8000); // max (precise) - test__trunctfhf2(65504.0, 0x7bff); + try test_f16_floatCast_f128(65504.0, 0x7bff); // max (rounded) - test__trunctfhf2(65519.0, 0x7bff); + try test_f16_floatCast_f128(65519.0, 0x7bff); // max (to +inf) - test__trunctfhf2(65520.0, 0x7c00); - test__trunctfhf2(65536.0, 0x7c00); - test__trunctfhf2(-65520.0, 0xfc00); + try test_f16_floatCast_f128(65520.0, 0x7c00); + try test_f16_floatCast_f128(65536.0, 0x7c00); + try test_f16_floatCast_f128(-65520.0, 0xfc00); - test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); - test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); - test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); - test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); + try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); + try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); + try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); + try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); } -test "trunctfxf2" { - try test__trunctfxf2(1.5, 1.5); - try test__trunctfxf2(2.5, 2.5); - try test__trunctfxf2(-2.5, -2.5); - try test__trunctfxf2(0.0, 0.0); -} - -fn test__trunctfxf2(a: f128, expected: f80) !void { - const x = __trunctfxf2(a); +fn test_f80_floatCast_f128(a: f128, expected: f80) !void { + const x = f80_floatCast_f128(a); try testing.expect(x == expected); } + +test f80_floatCast_f128 { + try test_f80_floatCast_f128(1.5, 1.5); + try test_f80_floatCast_f128(2.5, 2.5); + try test_f80_floatCast_f128(-2.5, -2.5); + try test_f80_floatCast_f128(0.0, 0.0); +} diff --git a/lib/compiler_rt/truncsfhf2.zig b/lib/compiler_rt/truncsfhf2.zig deleted file mode 100644 index e0b2b1e4bf2f15400c568f1c1656c8cb70bc03c8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncsfhf2.zig +++ /dev/null @@ -1,24 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.gnu_f16_abi) { - symbol(&__gnu_f2h_ieee, "__gnu_f2h_ieee"); - } else if (compiler_rt.want_aeabi) { - symbol(&__aeabi_f2h, "__aeabi_f2h"); - } - symbol(&__truncsfhf2, "__truncsfhf2"); -} - -pub fn __truncsfhf2(a: f32) callconv(.c) compiler_rt.F16T(f32) { - return @bitCast(truncf(f16, f32, a)); -} - -fn __gnu_f2h_ieee(a: f32) callconv(.c) compiler_rt.F16T(f32) { - return @bitCast(truncf(f16, f32, a)); -} - -fn __aeabi_f2h(a: f32) callconv(.{ .arm_aapcs = .{} }) u16 { - return @bitCast(truncf(f16, f32, a)); -} diff --git a/lib/compiler_rt/trunctfdf2.zig b/lib/compiler_rt/trunctfdf2.zig deleted file mode 100644 index ba909de73bf144b2f023e4f6366dac5a4ad0ea40..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfdf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfdf2, "__trunckfdf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtod, "_Qp_qtod"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__trunctfdf2, "_Q_qtod"); - } - symbol(&__trunctfdf2, "__trunctfdf2"); -} - -pub fn __trunctfdf2(a: f128) callconv(.c) f64 { - return truncf(f64, f128, a); -} - -fn _Qp_qtod(a: *const f128) callconv(.c) f64 { - return truncf(f64, f128, a.*); -} diff --git a/lib/compiler_rt/trunctfhf2.zig b/lib/compiler_rt/trunctfhf2.zig deleted file mode 100644 index 5af87f9c127180b49a15b8f3906252d7da162d26..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfhf2.zig +++ /dev/null @@ -1,14 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const truncf = @import("./truncf.zig").truncf; - -comptime { - symbol(&__trunctfhf2, "__trunctfhf2"); - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfhf2, "__trunckfhf2"); - } -} - -pub fn __trunctfhf2(a: f128) callconv(.c) compiler_rt.F16T(f128) { - return @bitCast(truncf(f16, f128, a)); -} diff --git a/lib/compiler_rt/trunctfsf2.zig b/lib/compiler_rt/trunctfsf2.zig deleted file mode 100644 index 8af51ca82f95b1dd36c7f27df20e6756b8e15396..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfsf2.zig +++ /dev/null @@ -1,22 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const truncf = @import("./truncf.zig").truncf; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_ppc_abi) { - symbol(&__trunctfsf2, "__trunckfsf2"); - } else if (compiler_rt.want_sparc64_abi) { - symbol(&_Qp_qtos, "_Qp_qtos"); - } else if (compiler_rt.want_sparc32_abi) { - symbol(&__trunctfsf2, "_Q_qtos"); - } - symbol(&__trunctfsf2, "__trunctfsf2"); -} - -pub fn __trunctfsf2(a: f128) callconv(.c) f32 { - return truncf(f32, f128, a); -} - -fn _Qp_qtos(a: *const f128) callconv(.c) f32 { - return truncf(f32, f128, a.*); -} diff --git a/lib/compiler_rt/trunctfxf2.zig b/lib/compiler_rt/trunctfxf2.zig deleted file mode 100644 index dfb9ef80402cda0360a111e436ba1f7c460bbc1f..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/trunctfxf2.zig +++ /dev/null @@ -1,67 +0,0 @@ -const math = @import("std").math; -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = compiler_rt.symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__trunctfxf2, "__trunctfxf2"); -} - -pub fn __trunctfxf2(a: f128) callconv(.c) f80 { - const src_sig_bits = math.floatMantissaBits(f128); - const dst_sig_bits = math.floatMantissaBits(f80) - 1; // -1 for the integer bit - - // Various constants whose values follow from the type parameters. - // Any reasonable optimizer will fold and propagate all of these. - const src_bits = @typeInfo(f128).float.bits; - const src_exp_bits = src_bits - src_sig_bits - 1; - const src_inf_exp = 0x7FFF; - - const src_inf = src_inf_exp << src_sig_bits; - const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); - const src_abs_mask = src_sign_mask - 1; - const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; - const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); - - // Break a into a sign and representation of the absolute value - const a_rep = @as(u128, @bitCast(a)); - const a_abs = a_rep & src_abs_mask; - const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; - const integer_bit = 1 << 63; - - var res: math.F80 = undefined; - - if (a_abs > src_inf) { - // a is NaN. - // Conjure the result by beginning with infinity, setting the qNaN - // bit and inserting the (truncated) trailing NaN field. - res.exp = 0x7fff; - res.fraction = 0x8000000000000000; - res.fraction |= @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))); - } else { - // The exponent of a is within the range of normal numbers in the - // destination format. We can convert by simply right-shifting with - // rounding, adding the explicit integer bit, and adjusting the exponent - res.fraction = @as(u64, @truncate(a_abs >> (src_sig_bits - dst_sig_bits))) | integer_bit; - res.exp = @truncate(a_abs >> src_sig_bits); - - const round_bits = a_abs & round_mask; - if (round_bits > halfway) { - // Round to nearest - const ov = @addWithOverflow(res.fraction, 1); - res.fraction = ov[0]; - res.exp += ov[1]; - res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry - } else if (round_bits == halfway) { - // Ties to even - const ov = @addWithOverflow(res.fraction, res.fraction & 1); - res.fraction = ov[0]; - res.exp += ov[1]; - res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry - } - if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals - } - - res.exp |= sign; - return res.toFloat(); -} diff --git a/lib/compiler_rt/truncxfdf2.zig b/lib/compiler_rt/truncxfdf2.zig deleted file mode 100644 index 6140d94181fbe10a5e83e880dff805e87b34fae8..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfdf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const symbol = @import("../compiler_rt.zig").symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__truncxfdf2, "__truncxfdf2"); -} - -fn __truncxfdf2(a: f80) callconv(.c) f64 { - return trunc_f80(f64, a); -} diff --git a/lib/compiler_rt/truncxfhf2.zig b/lib/compiler_rt/truncxfhf2.zig deleted file mode 100644 index 4c3e951bfe9b67ff88818e6a89f210851ddfcfb0..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfhf2.zig +++ /dev/null @@ -1,11 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; -const trunc_f80 = @import("./truncf.zig").trunc_f80; - -comptime { - symbol(&__truncxfhf2, "__truncxfhf2"); -} - -fn __truncxfhf2(a: f80) callconv(.c) compiler_rt.F16T(f80) { - return @bitCast(trunc_f80(f16, a)); -} diff --git a/lib/compiler_rt/truncxfsf2.zig b/lib/compiler_rt/truncxfsf2.zig deleted file mode 100644 index 8aaf7e6906a9da938835d2c36e931bfb21d07037..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/truncxfsf2.zig +++ /dev/null @@ -1,10 +0,0 @@ -const trunc_f80 = @import("./truncf.zig").trunc_f80; -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - symbol(&__truncxfsf2, "__truncxfsf2"); -} - -fn __truncxfsf2(a: f80) callconv(.c) f32 { - return trunc_f80(f32, a); -} diff --git a/lib/compiler_rt/udivmodei4.zig b/lib/compiler_rt/udivmodei4.zig index 41ba32cdbef1532de8b77e0f91db4bbf4b39f29a..e7c4f52cd1f0360307c5e0ab2232c8925b0b1792 100644 --- a/lib/compiler_rt/udivmodei4.zig +++ b/lib/compiler_rt/udivmodei4.zig @@ -6,7 +6,7 @@ const shr = std.math.shr; const shl = std.math.shl; const compiler_rt = @import("../compiler_rt.zig"); -const symbol = @import("../compiler_rt.zig").symbol; +const symbol = compiler_rt.symbol; const max_limbs = @divCeil(65535, 32); // max supported type is u65535 diff --git a/lib/compiler_rt/unorddf2.zig b/lib/compiler_rt/unorddf2.zig deleted file mode 100644 index 90da7451992ab5f8b003e5e2f85f93947f932197..0000000000000000000000000000000000000000 --- a/lib/compiler_rt/unorddf2.zig +++ /dev/null @@ -1,19 +0,0 @@ -const compiler_rt = @import("../compiler_rt.zig"); -const comparef = @import("./comparef.zig"); -const symbol = @import("../compiler_rt.zig").symbol; - -comptime { - if (compiler_rt.want_aeabi) { - symbol(&__aeabi_dcmpun, "__aeabi_dcmpun"); - } else { - symbol(&__unorddf2, "__unorddf2"); - } -} - -pub fn __unorddf2(a: f64, b: f64) callconv(.c) i32 { - return comparef.unordcmp(f64, a, b); -} - -fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return comparef.unordcmp(f64, a, b); -} diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig index 33502074f661d86b2b6778361e85ab89172242d9..aa36b73ac3e36e51bea58c59fea780d1cc222ae8 100644 --- a/lib/std/crypto/Certificate.zig +++ b/lib/std/crypto/Certificate.zig @@ -1211,7 +1211,7 @@ pub const rsa = struct { 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40, }, - else => @compileError("unreachable"), + else => comptime unreachable, }; em_index -= hash_der.len; @memcpy(em[em_index..][0..hash_der.len], hash_der); diff --git a/lib/std/math.zig b/lib/std/math.zig index b43bc8f5981ec9083596a17ac90df631fc31d33f..0beb62ae6a9eb10cdb78e887f900bebcde0612f4 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -75,7 +75,7 @@ pub const snan = float.snan; /// /// NaN values are never considered equal to any value. pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool { - assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); + comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); assert(tolerance >= 0); // Fast path for equal values (and signed zeros and infinites). @@ -103,7 +103,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool { /// /// NaN values are never considered equal to any value. pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool { - assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); + comptime assert(@typeInfo(T) == .float or @typeInfo(T) == .comptime_float); assert(tolerance > 0); // Fast path for equal values (and signed zeros and infinites). diff --git a/lib/std/math/atan2.zig b/lib/std/math/atan2.zig index f0c8aa0792046a94b900fba216dde87724ec8e1c..7c7bb4bb78e34d8d3b2c3403eba2e63d3ed1d3ce 100644 --- a/lib/std/math/atan2.zig +++ b/lib/std/math/atan2.zig @@ -252,8 +252,8 @@ test "atan2_32.special" { try expect(math.isNan(atan2_32(1.0, math.nan(f32)))); try expect(math.isNan(atan2_32(math.nan(f32), 1.0))); - try expect(atan2_32(0.0, 5.0) == 0.0); - try expect(atan2_32(-0.0, 5.0) == -0.0); + try expect(math.isPositiveZero(atan2_32(0.0, 5.0))); + try expect(math.isNegativeZero(atan2_32(-0.0, 5.0))); try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon)); //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? try expect(math.approxEqAbs(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon)); @@ -276,8 +276,8 @@ test "atan2_64.special" { try expect(math.isNan(atan2_64(1.0, math.nan(f64)))); try expect(math.isNan(atan2_64(math.nan(f64), 1.0))); - try expect(atan2_64(0.0, 5.0) == 0.0); - try expect(atan2_64(-0.0, 5.0) == -0.0); + try expect(math.isPositiveZero(atan2_64(0.0, 5.0))); + try expect(math.isNegativeZero(atan2_64(-0.0, 5.0))); try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon)); //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? try expect(math.approxEqAbs(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon)); diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 0ac83c50dc57047ff1a937182b717960b14e8f82..2315405a9e89549e26a875b00b51390fc3bc1b3d 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -527,6 +527,20 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { }; } +pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.Float { + if (target.cpu.has(.x86, .soft_float)) return .soft; + // Marks targets where clang does not even provide a usable C type. + const no_c_type_available = .soft; + switch (bits) { + else => unreachable, + 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available, + 32, 64 => {}, + 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available, + 128 => if (target.cTypeBitSize(.longdouble) <= 64) return no_c_type_available, + } + return .hard; +} + const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; diff --git a/src/link.zig b/src/link.zig index 84cbcbdcb78ea45a0e9e93242686f7f8f0f01748..7ce8363a3d77d9191b813cc86f2896e0285bec4e 100644 --- a/src/link.zig +++ b/src/link.zig @@ -2127,7 +2127,7 @@ pub fn resolveInputs( continue; }, } - @compileError("unreachable"); + comptime unreachable; } if (failed_libs.items.len > 0) { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index d13fc8e83d36590bb20b329f3accd39eae411a4d..0117c647880eb21fb9226abfc816a22ad2bcd2a7 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1845,7 +1845,7 @@ test "coerce between pointers of compatible differently-named floats" { 64 => f64, 80 => f80, 128 => f128, - else => @compileError("unreachable"), + else => comptime unreachable, }; var f1: F = 12.34; const f2: *c_longdouble = &f1; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 76b21b6f15316a95c3ee6d98a759ff06e8c03715..74a71249c65f6c2f839356c99bbd8416d5df1cd5 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -431,9 +431,9 @@ fn testSqrt(comptime T: type) !void { var inf: T = math.inf(T); try expect(math.isPositiveInf(@sqrt(inf))); var zero: T = 0.0; - try expect(@sqrt(zero) == 0.0); + try expect(math.isPositiveZero(@sqrt(zero))); var neg_zero: T = -0.0; - try expect(@sqrt(neg_zero) == 0.0); + try expect(math.isNegativeZero(@sqrt(neg_zero))); var neg_one: T = -1.0; try expect(math.isNan(@sqrt(neg_one))); var nan: T = math.nan(T); @@ -1501,9 +1501,9 @@ fn testNeg(comptime T: type) !void { // subnormals var zero: T = 0.0; - try expect(-zero == -0.0); + try expect(math.isNegativeZero(-zero)); var neg_zero: T = -0.0; - try expect(-neg_zero == 0.0); + try expect(math.isPositiveZero(-neg_zero)); var true_min: T = math.floatTrueMin(T); try expect(-true_min == -math.floatTrueMin(T)); var neg_true_min: T = -math.floatTrueMin(T); diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 6a44290f859261ad1c2f02974eb8525022fc0b25..c5ffdfa3e1872bfa58edb53b414b523660e9a9bb 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1267,7 +1267,7 @@ test "switch with complex item expressions" { test "switch evaluation order" { const eu: anyerror!u32 = 0; _ = eu catch |err| switch (err) { - if (true) @compileError("unreachable") => unreachable, + if (true) comptime unreachable => unreachable, else => unreachable, }; } diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig index c4353cd5df381e080489b9b5594df9d356277cc0..a57e93d0d1ca4bd502123b9e13ddcaeb7cbd9b68 100644 --- a/test/behavior/switch_on_captured_error.zig +++ b/test/behavior/switch_on_captured_error.zig @@ -243,7 +243,7 @@ test "switch on error union catch capture" { var a: error{}!u64 = 0; _ = &a; const b = a catch |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } @@ -829,7 +829,7 @@ test "switch on error union if else capture" { var a: error{}!u64 = 0; _ = &a; const b = if (a) |x| x else |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } @@ -840,7 +840,7 @@ test "switch on error union if else capture" { var a: error{}!u64 = 0; _ = &a; const b = if (a) |*x| x.* else |err| switch (err) { - undefined => @compileError("unreachable"), + undefined => comptime unreachable, }; try expectEqual(@as(u64, 0), b); } -- 2.54.0 From 3e26b9e957887e55e99046e908bc07200140d3f8 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 29 Jun 2026 09:48:37 -0400 Subject: [PATCH 050/215] codegen: change libc f128 suffix to match llvm --- lib/compiler_rt/cos.zig | 3 +- lib/compiler_rt/exp.zig | 5 +- lib/compiler_rt/exp2.zig | 5 +- lib/compiler_rt/fabs.zig | 5 +- lib/compiler_rt/floor_ceil.zig | 10 +- lib/compiler_rt/fma.zig | 5 +- lib/compiler_rt/fmax.zig | 5 +- lib/compiler_rt/fmin.zig | 5 +- lib/compiler_rt/fmod.zig | 5 +- lib/compiler_rt/log.zig | 5 +- lib/compiler_rt/log10.zig | 5 +- lib/compiler_rt/log2.zig | 5 +- lib/compiler_rt/round.zig | 3 +- lib/compiler_rt/sin.zig | 5 +- lib/compiler_rt/sincos.zig | 5 +- lib/compiler_rt/sqrt.zig | 6 +- lib/compiler_rt/tan.zig | 5 +- lib/compiler_rt/trunc.zig | 5 +- lib/zig.h | 2 +- src/codegen/aarch64/Select.zig | 38 ++--- src/codegen/wasm/CodeGen.zig | 32 ++-- src/codegen/wasm/Mir.zig | 36 ++-- src/codegen/x86_64/CodeGen.zig | 296 ++++++++++++++++----------------- src/target.zig | 2 +- stage1/zig.h | 2 +- test/behavior/floatop.zig | 1 + test/behavior/x86_64/unary.zig | 2 +- 27 files changed, 226 insertions(+), 277 deletions(-) diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 612698b1e9efb080804656c50e68cd6e0a2e8680..72ea9026472a1f8e31bca5cddc9e106cfd66155b 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -24,8 +24,7 @@ comptime { symbol(&cosf, "cosf"); symbol(&cos, "cos"); symbol(&__cosx, "__cosx"); - if (compiler_rt.want_ppc_abi) symbol(&cosq, "cosf128"); - symbol(&cosq, "cosq"); + symbol(&cosq, "cosf128"); symbol(&cosl, "cosl"); symbol(&cosl, "__cosl"); // required by musl } diff --git a/lib/compiler_rt/exp.zig b/lib/compiler_rt/exp.zig index ddec21869f166538e3497bb84050e55eba3ff33c..6f9d19ddb3adbfe743fd278ce9e458ae45341502 100644 --- a/lib/compiler_rt/exp.zig +++ b/lib/compiler_rt/exp.zig @@ -21,10 +21,7 @@ comptime { symbol(&expf, "expf"); symbol(&exp, "exp"); symbol(&__expx, "__expx"); - if (compiler_rt.want_ppc_abi) { - symbol(&expq, "expf128"); - } - symbol(&expq, "expq"); + symbol(&expq, "expf128"); symbol(&expl, "expl"); } diff --git a/lib/compiler_rt/exp2.zig b/lib/compiler_rt/exp2.zig index 36ee7c14c90be2c13dd0e09ca91d656a19a539a7..4f25cdec63332788d1bdda417503901b02ce6154 100644 --- a/lib/compiler_rt/exp2.zig +++ b/lib/compiler_rt/exp2.zig @@ -19,10 +19,7 @@ comptime { symbol(&exp2f, "exp2f"); symbol(&exp2, "exp2"); symbol(&__exp2x, "__exp2x"); - if (compiler_rt.want_ppc_abi) { - symbol(&exp2q, "exp2f128"); - } - symbol(&exp2q, "exp2q"); + symbol(&exp2q, "exp2f128"); symbol(&exp2l, "exp2l"); } diff --git a/lib/compiler_rt/fabs.zig b/lib/compiler_rt/fabs.zig index 50d2cc17d590a11615bdc471e6926af6c1f7bc6c..2238e65e61292668cb2e7bc2e2be3f090470b2e9 100644 --- a/lib/compiler_rt/fabs.zig +++ b/lib/compiler_rt/fabs.zig @@ -9,10 +9,7 @@ comptime { symbol(&fabsf, "fabsf"); symbol(&fabs, "fabs"); symbol(&__fabsx, "__fabsx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fabsq, "fabsf128"); - } - symbol(&fabsq, "fabsq"); + symbol(&fabsq, "fabsf128"); symbol(&fabsl, "fabsl"); } diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig index f31c352d026c549bd230c9d7d5f15677a85968ce..8bd82275e3787ae52587eb84c1391ee5949f616b 100644 --- a/lib/compiler_rt/floor_ceil.zig +++ b/lib/compiler_rt/floor_ceil.zig @@ -23,10 +23,7 @@ comptime { symbol(&floorf, "floorf"); symbol(&floor, "floor"); symbol(&__floorx, "__floorx"); - if (compiler_rt.want_ppc_abi) { - symbol(&floorq, "floorf128"); - } - symbol(&floorq, "floorq"); + symbol(&floorq, "floorf128"); symbol(&floorl, "floorl"); // ceil @@ -34,10 +31,7 @@ comptime { symbol(&ceilf, "ceilf"); symbol(&ceil, "ceil"); symbol(&__ceilx, "__ceilx"); - if (compiler_rt.want_ppc_abi) { - symbol(&ceilq, "ceilf128"); - } - symbol(&ceilq, "ceilq"); + symbol(&ceilq, "ceilf128"); symbol(&ceill, "ceill"); } diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig index f10d08fc63f2038fa98cd4b28c5d4ee8a2ca0a84..97bb57d4aae5aebe74c34925abacdb84f3aeef82 100644 --- a/lib/compiler_rt/fma.zig +++ b/lib/compiler_rt/fma.zig @@ -16,10 +16,7 @@ comptime { symbol(&fmaf, "fmaf"); symbol(&fma, "fma"); symbol(&__fmax, "__fmax"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmaq, "fmaf128"); - } - symbol(&fmaq, "fmaq"); + symbol(&fmaq, "fmaf128"); symbol(&fmal, "fmal"); } diff --git a/lib/compiler_rt/fmax.zig b/lib/compiler_rt/fmax.zig index cf323533952e542e126e11f69ec5a8352c37bcdb..f69912472044f62c50733968b382fec866d069c7 100644 --- a/lib/compiler_rt/fmax.zig +++ b/lib/compiler_rt/fmax.zig @@ -10,10 +10,7 @@ comptime { symbol(&fmaxf, "fmaxf"); symbol(&fmax, "fmax"); symbol(&__fmaxx, "__fmaxx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmaxq, "fmaxf128"); - } - symbol(&fmaxq, "fmaxq"); + symbol(&fmaxq, "fmaxf128"); symbol(&fmaxl, "fmaxl"); } diff --git a/lib/compiler_rt/fmin.zig b/lib/compiler_rt/fmin.zig index 48b5dcdc225118ce3a2096b15c98b0b534f75ae3..bece9262f2a673919e33260576c2ce7d8730cdee 100644 --- a/lib/compiler_rt/fmin.zig +++ b/lib/compiler_rt/fmin.zig @@ -10,10 +10,7 @@ comptime { symbol(&fminf, "fminf"); symbol(&fmin, "fmin"); symbol(&__fminx, "__fminx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fminq, "fminf128"); - } - symbol(&fminq, "fminq"); + symbol(&fminq, "fminf128"); symbol(&fminl, "fminl"); } diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index 636138516bf1f13d2a15b597d21fd6a617e7ee0d..951b90d06e529e8a3a2606d7fe0eff1dcd9d667a 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -12,10 +12,7 @@ comptime { symbol(&fmodf, "fmodf"); symbol(&fmod, "fmod"); symbol(&__fmodx, "__fmodx"); - if (compiler_rt.want_ppc_abi) { - symbol(&fmodq, "fmodf128"); - } - symbol(&fmodq, "fmodq"); + symbol(&fmodq, "fmodf128"); symbol(&fmodl, "fmodl"); } diff --git a/lib/compiler_rt/log.zig b/lib/compiler_rt/log.zig index 9f632f69ff93a9c05663104c5429c7c8e787e761..8b2937921d5998941e7731ac8decce71f60c85cb 100644 --- a/lib/compiler_rt/log.zig +++ b/lib/compiler_rt/log.zig @@ -18,10 +18,7 @@ comptime { symbol(&logf, "logf"); symbol(&log, "log"); symbol(&__logx, "__logx"); - if (compiler_rt.want_ppc_abi) { - symbol(&logq, "logf128"); - } - symbol(&logq, "logq"); + symbol(&logq, "logf128"); symbol(&logl, "logl"); } diff --git a/lib/compiler_rt/log10.zig b/lib/compiler_rt/log10.zig index 6a554e0ea79ff597dfdeeea31477e1c6ebfbac1c..0813c1ae7c0dc6d71ae7aa2699f17e05bdffe039 100644 --- a/lib/compiler_rt/log10.zig +++ b/lib/compiler_rt/log10.zig @@ -18,10 +18,7 @@ comptime { symbol(&log10f, "log10f"); symbol(&log10, "log10"); symbol(&__log10x, "__log10x"); - if (compiler_rt.want_ppc_abi) { - symbol(&log10q, "log10f128"); - } - symbol(&log10q, "log10q"); + symbol(&log10q, "log10f128"); symbol(&log10l, "log10l"); } diff --git a/lib/compiler_rt/log2.zig b/lib/compiler_rt/log2.zig index b748a0af826586065f1f5369a6f1c61492b4cf99..0806fb079419787d33dd3b825b4057aac51f1397 100644 --- a/lib/compiler_rt/log2.zig +++ b/lib/compiler_rt/log2.zig @@ -19,10 +19,7 @@ comptime { symbol(&log2f, "log2f"); symbol(&log2, "log2"); symbol(&__log2x, "__log2x"); - if (compiler_rt.want_ppc_abi) { - symbol(&log2q, "log2f128"); - } - symbol(&log2q, "log2q"); + symbol(&log2q, "log2f128"); symbol(&log2l, "log2l"); } diff --git a/lib/compiler_rt/round.zig b/lib/compiler_rt/round.zig index 6c86984605af2d246a4e582851a5d172a67d7c69..ffcaed60774e70e5067ff107380a8af5a057d718 100644 --- a/lib/compiler_rt/round.zig +++ b/lib/compiler_rt/round.zig @@ -18,8 +18,7 @@ comptime { symbol(&roundf, "roundf"); symbol(&round, "round"); symbol(&__roundx, "__roundx"); - if (compiler_rt.want_ppc_abi) symbol(&roundq, "roundf128"); - symbol(&roundq, "roundq"); + symbol(&roundq, "roundf128"); symbol(&roundl, "roundl"); } diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index fe818922fe4af6542dc88fd682367860ae4908da..3e0b8f0cbd823b0e57fe0172217c7726955c7fd1 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -24,10 +24,7 @@ comptime { symbol(&sinf, "sinf"); symbol(&sin, "sin"); symbol(&__sinx, "__sinx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sinq, "sinf128"); - } - symbol(&sinq, "sinq"); + symbol(&sinq, "sinf128"); symbol(&sinl, "sinl"); symbol(&sinl, "__sinl"); // required by musl } diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index 6d2b9f007a90f94c158bb636d3fcd1d8e6b40a7c..d43f55b623954f602edf850b75d409931b1aaee6 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -18,10 +18,7 @@ comptime { symbol(&sincosf, "sincosf"); symbol(&sincos, "sincos"); symbol(&sincosx, "__sincosx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sincosq, "sincosf128"); - } - symbol(&sincosq, "sincosq"); + symbol(&sincosq, "sincosf128"); symbol(&sincosl, "sincosl"); } diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index 56e43a42fcdd437811ad00d7290de45d5cee82f3..a37fe429c1458153dded08805982d118dedb8ebb 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -17,14 +17,12 @@ comptime { symbol(&sqrtf, "sqrtf"); symbol(&sqrt, "sqrt"); symbol(&__sqrtx, "__sqrtx"); - if (compiler_rt.want_ppc_abi) { - symbol(&sqrtq, "sqrtf128"); - } else if (compiler_rt.want_sparc64_abi) { + symbol(&sqrtq, "sqrtf128"); + if (compiler_rt.want_sparc64_abi) { symbol(&_Qp_sqrt, "_Qp_sqrt"); } else if (compiler_rt.want_sparc32_abi) { symbol(&sqrtq, "_Q_sqrt"); } - symbol(&sqrtq, "sqrtq"); symbol(&sqrtl, "sqrtl"); } diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 038ac85b6dc2dd9e7d742936bd0df3095dc4b9ec..4ee4440dd6c5cd7417842de27084cab36ae85907 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -28,10 +28,7 @@ comptime { symbol(&tanf, "tanf"); symbol(&tan, "tan"); symbol(&__tanx, "__tanx"); - if (compiler_rt.want_ppc_abi) { - symbol(&tanq, "tanf128"); - } - symbol(&tanq, "tanq"); + symbol(&tanq, "tanf128"); symbol(&tanl, "tanl"); } diff --git a/lib/compiler_rt/trunc.zig b/lib/compiler_rt/trunc.zig index 0653178b54b50256e43168d377f59377f34dcc14..0dbacf0e9d822385a8dc558a29bf0401f6d97e21 100644 --- a/lib/compiler_rt/trunc.zig +++ b/lib/compiler_rt/trunc.zig @@ -17,10 +17,7 @@ comptime { symbol(&truncf, "truncf"); symbol(&trunc, "trunc"); symbol(&__truncx, "__truncx"); - if (compiler_rt.want_ppc_abi) { - symbol(&truncq, "truncf128"); - } - symbol(&truncq, "truncq"); + symbol(&truncq, "truncf128"); symbol(&truncl, "truncl"); } diff --git a/lib/zig.h b/lib/zig.h index fbc924ca334e99eb12d2f37e3ebffa970ced7b9d..fc2f9479bea2bf9599dfcaebe35294fed98b4db4 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -3835,7 +3835,7 @@ typedef zig_u128 zig_f80; #endif #define zig_has_f128 1 -#define zig_libc_name_f128(name) name##q +#define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 30387bfe8a37719577b57391f6f270e71e8238e2..73cd6ea1e357e38497633fbcbb5af744f1815e1a 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2099,7 +2099,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "truncf", 64 => "trunc", 80 => "__truncx", - 128 => "truncq", + 128 => "truncf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2113,7 +2113,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "floorf", 64 => "floor", 80 => "__floorx", - 128 => "floorq", + 128 => "floorf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2431,7 +2431,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmodf", 64 => "fmod", 80 => "__fmodx", - 128 => "fmodq", + 128 => "fmodf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); @@ -2599,7 +2599,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmaxf", 64 => "fmax", 80 => "__fmaxx", - 128 => "fmaxq", + 128 => "fmaxf128", }, .min => switch (bits) { else => unreachable, @@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fminf", 64 => "fmin", 80 => "__fminx", - 128 => "fminq", + 128 => "fminf128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -4055,7 +4055,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "sqrtf", 64 => "sqrt", 80 => "__sqrtx", - 128 => "sqrtq", + 128 => "sqrtf128", }, .floor => switch (bits) { else => unreachable, @@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "floorf", 64 => "floor", 80 => "__floorx", - 128 => "floorq", + 128 => "floorf128", }, .ceil => switch (bits) { else => unreachable, @@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "ceilf", 64 => "ceil", 80 => "__ceilx", - 128 => "ceilq", + 128 => "ceilf128", }, .round => switch (bits) { else => unreachable, @@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "roundf", 64 => "round", 80 => "__roundx", - 128 => "roundq", + 128 => "roundf128", }, .trunc_float => switch (bits) { else => unreachable, @@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "truncf", 64 => "trunc", 80 => "__truncx", - 128 => "truncq", + 128 => "truncf128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -4147,7 +4147,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "sinf", 64 => "sin", 80 => "__sinx", - 128 => "sinq", + 128 => "sinf128", }, .cos => switch (bits) { else => unreachable, @@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "cosf", 64 => "cos", 80 => "__cosx", - 128 => "cosq", + 128 => "cosf128", }, .tan => switch (bits) { else => unreachable, @@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "tanf", 64 => "tan", 80 => "__tanx", - 128 => "tanq", + 128 => "tanf128", }, .exp => switch (bits) { else => unreachable, @@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "expf", 64 => "exp", 80 => "__expx", - 128 => "expq", + 128 => "expf128", }, .exp2 => switch (bits) { else => unreachable, @@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "exp2f", 64 => "exp2", 80 => "__exp2x", - 128 => "exp2q", + 128 => "exp2f128", }, .log => switch (bits) { else => unreachable, @@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "logf", 64 => "log", 80 => "__logx", - 128 => "logq", + 128 => "logf128", }, .log2 => switch (bits) { else => unreachable, @@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "log2f", 64 => "log2", 80 => "__log2x", - 128 => "log2q", + 128 => "log2f128", }, .log10 => switch (bits) { else => unreachable, @@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "log10f", 64 => "log10", 80 => "__log10x", - 128 => "log10q", + 128 => "log10f128", }, }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, @@ -7118,7 +7118,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 32 => "fmaf", 64 => "fma", 80 => "__fmax", - 128 => "fmaq", + 128 => "fmaf128", }, .reloc = .{ .label = @intCast(isel.instructions.items.len) }, }); diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index e0e73040cab9dedecaaca4c4f843e647e87edcd5..3dc36619686e53a6112e3cc81ec9ccd3f902e0c6 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -4340,7 +4340,7 @@ fn floatRem(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fmodx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fmodq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fmodf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4376,7 +4376,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fmaxx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fmaxq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fmaxf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4387,7 +4387,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), .f80 => return cg.callIntrinsic(.__fminx, &.{ .f80_type, .f80_type }, Type.f80, &.{ lhs, rhs }), - .f128 => return cg.callIntrinsic(.fminq, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), + .f128 => return cg.callIntrinsic(.fminf128, &.{ .f128_type, .f128_type }, Type.f128, &.{ lhs, rhs }), } } @@ -4405,7 +4405,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__sqrtx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.sqrtq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.sqrtf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4415,7 +4415,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__sinx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.sinq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.sinf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4425,7 +4425,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__cosx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.cosq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.cosf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4435,7 +4435,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__tanx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.tanq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.tanf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4445,7 +4445,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__expx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.expq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.expf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4455,7 +4455,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__exp2x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.exp2q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.exp2f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4465,7 +4465,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__logx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.logq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.logf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4475,7 +4475,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__log2x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.log2q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.log2f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4485,7 +4485,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}), .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}), .f80 => return cg.callIntrinsic(.__log10x, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.log10q, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.log10f128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4503,7 +4503,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__floorx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.floorq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.floorf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4521,7 +4521,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__ceilx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.ceilq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.ceilf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4539,7 +4539,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__roundx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.roundq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.roundf128, &.{.f128_type}, Type.f128, &.{arg}), } } @@ -4557,7 +4557,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { return .stack; }, .f80 => return cg.callIntrinsic(.__truncx, &.{.f80_type}, Type.f80, &.{arg}), - .f128 => return cg.callIntrinsic(.truncq, &.{.f128_type}, Type.f128, &.{arg}), + .f128 => return cg.callIntrinsic(.truncf128, &.{.f128_type}, Type.f128, &.{arg}), } } diff --git a/src/codegen/wasm/Mir.zig b/src/codegen/wasm/Mir.zig index 8e5f1c32f958d8ea2403ea2260a421da08e153c9..bbb41312990a836c336b6a3aa303ba2f0e363521 100644 --- a/src/codegen/wasm/Mir.zig +++ b/src/codegen/wasm/Mir.zig @@ -991,48 +991,48 @@ pub const Intrinsic = enum(u32) { __udivti3, __umodei5, __umodti3, - ceilq, + ceilf128, cos, cosf, - cosq, + cosf128, exp, exp2, exp2f, - exp2q, + exp2f128, expf, - expq, - fabsq, - floorq, + expf128, + fabsf128, + floorf128, fma, fmaf, - fmaq, + fmaf128, fmax, fmaxf, - fmaxq, + fmaxf128, fmin, fminf, - fminq, + fminf128, fmod, fmodf, - fmodq, + fmodf128, log, log10, log10f, - log10q, + log10f128, log2, log2f, - log2q, + log2f128, logf, - logq, - roundq, + logf128, + roundf128, sin, sinf, - sinq, - sqrtq, + sinf128, + sqrtf128, tan, tanf, - tanq, - truncq, + tanf128, + truncf128, memcpy, memmove, memset, diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index d499ef406fc67f0a7a4fe8c81390b6ad434a36a5..da82d324608abdc1a1dabc4c691c41b4f9c470d5 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, .unused, .unused, .unused, @@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .zero => "truncq", - .down => "floorq", + .zero => "truncf128", + .down => "floorf128", } } }, .unused, .unused, @@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, .unused, .unused, .unused, @@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .unused, .unused, .unused, @@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rcx } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .f128, .kind = .mem }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .u64, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .mem }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, .{ .type = .u64, .kind = .{ .reg = .rax } }, @@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .mem }, .{ .type = .usize, .kind = .{ .reg = .rax } }, .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } }, @@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rcx } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, .{ .type = .f128, .kind = .{ .reg = .rdx } }, .{ .type = .f128, .kind = .mem }, .{ .type = .f128, .kind = .{ .reg = .rax } }, @@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .unused, .unused, .unused, @@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .unused, .unused, .unused, @@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, + .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .unused, .unused, @@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { else => unreachable, - .down => "floorq", - .up => "ceilq", - .zero => "truncq", + .down => "floorf128", + .up => "ceilf128", + .zero => "truncf128", } } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, @@ -142552,7 +142552,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142584,7 +142584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142616,7 +142616,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -142649,7 +142649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -142683,7 +142683,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -142717,7 +142717,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152785,7 +152785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152817,7 +152817,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152849,7 +152849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -152882,7 +152882,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152916,7 +152916,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -152950,7 +152950,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163019,7 +163019,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163051,7 +163051,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163083,7 +163083,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .unused, .unused, .unused, @@ -163116,7 +163116,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163150,7 +163150,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -163184,7 +163184,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164816,7 +164816,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164848,7 +164848,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164880,7 +164880,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .extra_temps = .{ .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .unused, .unused, .unused, @@ -164913,7 +164913,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164947,7 +164947,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -164981,7 +164981,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, .{ .type = .f128, .kind = .mem }, .unused, .unused, @@ -172785,7 +172785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .call_frame = .{ .alignment = .@"16" }, .extra_temps = .{ - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172818,7 +172818,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172852,7 +172852,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172889,7 +172889,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172926,7 +172926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .unused, .unused, .unused, @@ -172963,7 +172963,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -173000,7 +173000,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, @@ -173037,7 +173037,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 2, .at = 2 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, + .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, .unused, .unused, diff --git a/src/target.zig b/src/target.zig index 0ed4053701fd696db7540b42dbf5aaf890e47921..e249be39947d8d99f6f9eef6bd15b271887625fe 100644 --- a/src/target.zig +++ b/src/target.zig @@ -876,7 +876,7 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 { 32 => "f", 64 => "", 80 => "x", // Non-standard - 128 => "q", // Non-standard (mimics convention in GCC libquadmath) + 128 => "f128", else => unreachable, }; } diff --git a/stage1/zig.h b/stage1/zig.h index fbc924ca334e99eb12d2f37e3ebffa970ced7b9d..fc2f9479bea2bf9599dfcaebe35294fed98b4db4 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -3835,7 +3835,7 @@ typedef zig_u128 zig_f80; #endif #define zig_has_f128 1 -#define zig_libc_name_f128(name) name##q +#define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) #if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 74a71249c65f6c2f839356c99bbd8416d5df1cd5..f8fbab0aaefd3d3d4b39d472eb84e41b9382dc8f 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -381,6 +381,7 @@ test "@sqrt f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.os.tag == .freebsd) { // TODO https://github.com/ziglang/zig/issues/10875 diff --git a/test/behavior/x86_64/unary.zig b/test/behavior/x86_64/unary.zig index 2b2a9e288b30c1c0a1d0ab1de61b23522582b6e8..263505f090d09aa3b76eddb309b0d6bd531057dc 100644 --- a/test/behavior/x86_64/unary.zig +++ b/test/behavior/x86_64/unary.zig @@ -56,7 +56,7 @@ fn unary(comptime op: anytype, comptime opts: struct { f32 => libc_name ++ "f", f64 => libc_name, f80 => "__" ++ libc_name ++ "x", - f128 => libc_name ++ "q", + f128 => libc_name ++ "f128", else => break :libc, }, .library_name = switch (@import("builtin").object_format) { -- 2.54.0 From 69dd10144fc723d8006f2e563fc3edd82ee4b368 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 11:33:42 -0400 Subject: [PATCH 051/215] Type: make `f80` not extern compatible on targets lacking such a type Closes #35802 --- src/Sema.zig | 2 +- src/Type.zig | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 129b9104d385499e8443b4fc45dcf6c2e26497e8..bb2cd4eff32547c659ec0e7f14fddf3cc4b07d18 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25675,7 +25675,6 @@ pub fn explainWhyTypeIsNotExtern( .@"opaque", .bool, - .float, .@"anyframe", => unreachable, // these *are* allowed @@ -25684,6 +25683,7 @@ pub fn explainWhyTypeIsNotExtern( try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); }, + .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}), .pointer => if (ty.isSlice(zcu)) { try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { diff --git a/src/Type.zig b/src/Type.zig index 32e49a05c26a8ee5459164c02f987c92704f0f65..56b2388710b2b919a2a429fd3afa0dfa515bcf66 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3122,7 +3122,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool .@"opaque", .bool, - .float, .@"anyframe", => true, @@ -3144,6 +3143,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool 24, 48 => zcu.getTarget().cpu.arch == .ez80, else => false, }, + .float => switch (ty.floatBits(zcu.getTarget())) { + else => true, + 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80, + }, .@"fn" => { if (position != .other) return false; return validateExternCallconv(ty.fnCallingConvention(zcu)); -- 2.54.0 From 865f329e4f9fd097bb9739566045f9b7179521c4 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 25 Jun 2026 01:53:50 -0400 Subject: [PATCH 052/215] cbe: update for compiler_rt abi changes * `tools/generate_c_size_and_align_checks.zig`: superceded by any cbe output artifact * `cTypePreferredAlignment`: no uses, if brought back, cbe should be updated to verify `__alignof` Closes #19991 Closes #20881 Closes #35523 --- lib/compiler/test_runner.zig | 1 + lib/std/Io/Semaphore.zig | 2 - lib/std/Io/Writer.zig | 6 +- lib/std/Random/RomuTrio.zig | 1 - lib/std/Random/Xoshiro256.zig | 2 - lib/std/Target.zig | 114 - lib/std/bit_set.zig | 2 - lib/std/crypto/aes.zig | 4 +- lib/std/crypto/aes_ocb.zig | 10 - lib/std/crypto/ecdsa.zig | 21 - lib/std/crypto/ff.zig | 4 - lib/std/crypto/pcurves/p384.zig | 10 +- lib/std/crypto/pcurves/secp256k1.zig | 12 +- lib/std/debug/cpu_context.zig | 2 + lib/std/fmt.zig | 2 - lib/std/fmt/float.zig | 2 +- lib/std/fs/test.zig | 5 +- lib/std/hash/auto_hash.zig | 2 +- lib/std/hash/xxhash.zig | 4 - lib/std/math.zig | 3 +- lib/std/math/big/int_test.zig | 39 +- lib/std/math/log10.zig | 5 - lib/std/math/signbit.zig | 1 + lib/std/mem.zig | 88 +- lib/std/os/linux/aarch64.zig | 2 +- lib/std/os/linux/s390x.zig | 36 +- lib/std/testing/Smith.zig | 2 +- lib/std/zon/parse.zig | 7 +- lib/std/zon/stringify.zig | 3 - lib/zig.h | 3933 +++++++++++++++----- src/codegen/c.zig | 1207 +++--- src/codegen/c/type/render_defs.zig | 182 +- src/link.zig | 2 +- src/link/C.zig | 49 +- test/behavior/abs.zig | 2 - test/behavior/align.zig | 2 - test/behavior/basic.zig | 1 - test/behavior/bit_shifting.zig | 1 - test/behavior/bitcast.zig | 7 +- test/behavior/cast.zig | 11 +- test/behavior/cast_int.zig | 1 - test/behavior/eval.zig | 1 - test/behavior/extern.zig | 1 - test/behavior/field_parent_ptr.zig | 2 - test/behavior/floatop.zig | 8 - test/behavior/fn.zig | 1 - test/behavior/math.zig | 29 - test/behavior/maximum_minimum.zig | 1 - test/behavior/muladd.zig | 4 - test/behavior/packed-struct.zig | 4 - test/behavior/pointers.zig | 2 +- test/behavior/saturating_arithmetic.zig | 7 - test/behavior/struct.zig | 8 +- test/behavior/switch_loop.zig | 3 +- test/behavior/truncate.zig | 1 - test/behavior/union.zig | 6 - test/behavior/vector.zig | 5 - test/standalone/build.zig | 1 - test/tests.zig | 64 +- tools/generate_c_size_and_align_checks.zig | 62 - 60 files changed, 3993 insertions(+), 2007 deletions(-) delete mode 100644 tools/generate_c_size_and_align_checks.zig diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 62c09fe22800abc8aeb462dbd8c8beffe0ef7925..4e9502656c56f1e8cc43a03529d5d2599abbace5 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -377,6 +377,7 @@ pub fn mainSimple() anyerror!void { else => false, }; + testing.allocator_instance = .init(std.heap.page_allocator, .{}); testing.io_instance = .init(testing.allocator, .{}); var passed: u64 = 0; diff --git a/lib/std/Io/Semaphore.zig b/lib/std/Io/Semaphore.zig index 1f486750487ed8cd66c39306998d7434e8cd4df7..8f2137b80220fa26c19173d8a3db1098eb24f570 100644 --- a/lib/std/Io/Semaphore.zig +++ b/lib/std/Io/Semaphore.zig @@ -4,8 +4,6 @@ //! This API supports static initialization and does not require deinitialization. const Semaphore = @This(); -const builtin = @import("builtin"); - const std = @import("../std.zig"); const Io = std.Io; const testing = std.testing; diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index ca9564edff39fe329f5114aa2a2fba41c4a6fe02..c243c8551f4917ef210159743f0d55ba749d1e6a 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize { } /// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes. -pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { +pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void { var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined; std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); return w.writeAll(&bytes); @@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built /// The function is inline to avoid the dead code in case `endian` is /// comptime-known and matches host endianness. -pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void { +pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void { switch (@typeInfo(@TypeOf(value))) { .@"struct" => |info| switch (info.layout) { .auto => @compileError("ill-defined memory layout"), @@ -907,7 +907,7 @@ pub inline fn writeSliceEndian( w: *Writer, Elem: type, slice: []const Elem, - endian: std.builtin.Endian, + endian: std.lang.Endian, ) Error!void { switch (@typeInfo(Elem)) { .@"struct" => |info| comptime assert(info.layout != .auto), diff --git a/lib/std/Random/RomuTrio.zig b/lib/std/Random/RomuTrio.zig index 9f005bf2f9fac8082eb4e71355dc90c73280d2b9..7352308f0d18eb6ccbe0b506bdfd4138443c89de 100644 --- a/lib/std/Random/RomuTrio.zig +++ b/lib/std/Random/RomuTrio.zig @@ -122,7 +122,6 @@ test fill { } test "buf seeding test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }); const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 }; var r = RomuTrio.init(0); diff --git a/lib/std/Random/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig index 6cb0583d982622b3f7df21b94368b03ddeb80c17..9c1ea9cfec6843cf2b9151ac08cb44aebd810936 100644 --- a/lib/std/Random/Xoshiro256.zig +++ b/lib/std/Random/Xoshiro256.zig @@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void { } test "sequence" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - var r = Xoshiro256.init(0); const seq1 = [_]u64{ diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 6124ffd96597d33dbd1027ae8b5757989b536c7a..5dc5075bada694841849a65904acdaa60471a23b 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3575,120 +3575,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { ); } -pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { - // Overrides for unusual alignments - switch (target.cpu.arch) { - .arc, .arceb => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - .avr, - .ez80, - => return 1, - .x86 => switch (target.os.tag) { - .windows, .uefi => switch (c_type) { - .longdouble => switch (target.abi) { - .gnu => return 4, - else => return 8, - }, - else => {}, - }, - else => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - }, - .m68k => switch (c_type) { - .int, .uint, .long, .ulong => return 2, - else => {}, - }, - .wasm32, .wasm64 => switch (target.os.tag) { - .emscripten => switch (c_type) { - .longdouble => return 8, - else => {}, - }, - else => {}, - }, - else => {}, - } - - // Next-power-of-two-aligned, up to a maximum. - return @min( - std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), - @as(u16, switch (target.cpu.arch) { - .x86_16, - .msp430, - => 2, - - .arc, - .arceb, - .csky, - .kalimba, - .microblaze, - .microblazeel, - .or1k, - .propeller, - .sh, - .sheb, - .xcore, - .xtensa, - .xtensaeb, - => 4, - - .amdgcn, - .arm, - .armeb, - .bpfeb, - .bpfel, - .hexagon, - .hppa, - .lanai, - .m68k, - .m88k, - .mips, - .mipsel, - .nvptx, - .nvptx64, - .s390x, - .sparc, - .thumb, - .thumbeb, - .x86, - => 8, - - .aarch64, - .aarch64_be, - .alpha, - .hppa64, - .kvx, - .loongarch32, - .loongarch64, - .mips64, - .mips64el, - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - .riscv32, - .riscv32be, - .riscv64, - .riscv64be, - .sparc64, - .spirv32, - .spirv64, - .ve, - .wasm32, - .wasm64, - .x86_64, - => 16, - - .avr, - .ez80, - => unreachable, // Handled above. - }), - ); -} - pub fn cMaxIntAlignment(target: *const Target) u16 { return switch (target.cpu.arch) { .avr, diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index b7920e20124d4e04f78662a14861ed7f9f6ae711..1a31e3b1a50b55cb8f26aa63789c1a04e9f6bc84 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void { } test Integer { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try testStaticBitSet(Integer(0)); try testStaticBitSet(Integer(1)); try testStaticBitSet(Integer(2)); diff --git a/lib/std/crypto/aes.zig b/lib/std/crypto/aes.zig index acf3a72e1fd2616a6074f896c3cf53da02364c48..54d1bd0dc8474d9eb299ca823864fdc9a1a001ea 100644 --- a/lib/std/crypto/aes.zig +++ b/lib/std/crypto/aes.zig @@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes); const has_avx = builtin.cpu.has(.x86, .avx); const has_armaes = builtin.cpu.has(.aarch64, .aes); // C backend doesn't currently support passing vectors to inline asm. -const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: { +const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: { break :impl @import("aes/aesni.zig"); -} else if (builtin.cpu.arch == .aarch64 and builtin.zig_backend != .stage2_c and has_armaes) impl: { +} else if (builtin.cpu.arch == .aarch64 and (builtin.zig_backend != .stage2_c or !builtin.os.tag.isDarwin()) and has_armaes) impl: { break :impl @import("aes/armcrypto.zig"); } else impl: { break :impl @import("aes/soft.zig"); diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig index 36e2aaa84cbb852ab0dc8b20ccf4aca8ecfea710..5c3af0615112822c58c892fa373150e23050dfcc 100644 --- a/lib/std/crypto/aes_ocb.zig +++ b/lib/std/crypto/aes_ocb.zig @@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes; const testing = std.testing; test "AesOcb test vector 1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -281,8 +279,6 @@ test "AesOcb test vector 1" { } test "AesOcb test vector 2" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -303,8 +299,6 @@ test "AesOcb test vector 2" { } test "AesOcb test vector 3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -329,8 +323,6 @@ test "AesOcb test vector 3" { } test "AesOcb test vector 4" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -356,8 +348,6 @@ test "AesOcb test vector 4" { } test "AesOcb in-place encryption-decryption" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig index b111b8e52a706b7b869a8091747934291912eff6..8977851b44ea04596ff686ec46fa576aa9b9693f 100644 --- a/lib/std/crypto/ecdsa.zig +++ b/lib/std/crypto/ecdsa.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const std = @import("std"); const crypto = std.crypto; const fmt = std.fmt; @@ -415,8 +414,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { } test "Basic operations over EcdsaP384Sha384" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); @@ -432,8 +429,6 @@ test "Basic operations over EcdsaP384Sha384" { } test "Basic operations over Secp256k1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaSecp256k1Sha256oSha256; const kp = Scheme.KeyPair.generate(io); @@ -449,8 +444,6 @@ test "Basic operations over Secp256k1" { } test "Basic operations over EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); const kp = Scheme.KeyPair.generate(io); @@ -466,8 +459,6 @@ test "Basic operations over EcdsaP384Sha256" { } test "Verifying a existing signature with EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); // zig fmt: off const sk_bytes = [_]u8{ @@ -503,8 +494,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" { } test "Prehashed message operations" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP256Sha256; @@ -539,8 +528,6 @@ const TestVector = struct { }; test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // well-formed DER encoding -> expected valid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" }, @@ -711,8 +698,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { } test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" }, @@ -1026,8 +1011,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" }, @@ -1243,8 +1226,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" }, @@ -1631,8 +1612,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { } test "Sec1 encoding/decoding" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); diff --git a/lib/std/crypto/ff.zig b/lib/std/crypto/ff.zig index bf9584dfa3ad033652130705937972171370669c..c59dc92c61d66a457aabd11175f9ee0c5f83e582 100644 --- a/lib/std/crypto/ff.zig +++ b/lib/std/crypto/ff.zig @@ -966,8 +966,6 @@ const ct_unprotected = struct { }; test "finite field arithmetic" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const M = Modulus(256); const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233); var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733); @@ -1066,8 +1064,6 @@ test "finite field arithmetic" { } fn testCt(ct_: anytype) !void { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const l0: Limb = 0; const l1: Limb = 1; try testing.expectEqual(l1, ct_.select(true, l1, l0)); diff --git a/lib/std/crypto/pcurves/p384.zig b/lib/std/crypto/pcurves/p384.zig index 8bc0ec36f2d64e3c6d73e5d782b6df143c6a859f..7b97bf92b1b5ab138659e1348822d06885017fc5 100644 --- a/lib/std/crypto/pcurves/p384.zig +++ b/lib/std/crypto/pcurves/p384.zig @@ -56,7 +56,7 @@ pub const P384 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!P384 { + pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!P384 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -395,7 +395,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mul(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -407,7 +407,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulPublic(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, true); @@ -419,7 +419,7 @@ pub const P384 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -478,7 +478,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/p384.zig"); } diff --git a/lib/std/crypto/pcurves/secp256k1.zig b/lib/std/crypto/pcurves/secp256k1.zig index 9ce8b944ebbffc071bcdd3be90fa47463525289e..3c36b9b2ed49d45dc1a13c0d9aab2a69d6dd3398 100644 --- a/lib/std/crypto/pcurves/secp256k1.zig +++ b/lib/std/crypto/pcurves/secp256k1.zig @@ -51,7 +51,7 @@ pub const Secp256k1 = struct { }; /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L). - pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) NonCanonicalError!SplitScalar { + pub fn splitScalar(s: [32]u8, endian: std.lang.Endian) NonCanonicalError!SplitScalar { const b1_neg_s = comptime s: { var buf: [32]u8 = undefined; mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little); @@ -109,7 +109,7 @@ pub const Secp256k1 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { + pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -423,7 +423,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -435,7 +435,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { + pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); const zero = comptime scalar.Scalar.zero.toBytes(.little); if (mem.eql(u8, &zero, &s)) { @@ -497,7 +497,7 @@ pub const Secp256k1 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -556,7 +556,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/secp256k1.zig"); } diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 36be9fe60e0ebe084ab2e045702bc91628ff9bf6..ab90b9b2c27e374ef56148334eb83fcc13d6ba75 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) { .mips64el, .or1k, .s390x, + .sh, + .sheb, .x86, .x86_64, .xtensa, diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 7cdc44269cdc95b492eb8ac718a53d7fe721af55..0c3dba4a7a95ff9a68f8d9f64d082c35565134a7 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1082,8 +1082,6 @@ test "float.libc.sanity" { } test "union" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const TU = union(enum) { float: f32, int: u32, diff --git a/lib/std/fmt/float.zig b/lib/std/fmt/float.zig index 25bf97f22ae52df136be9dbbdeab2e0fdedfdc18..e055959825832e1889d6d2c0fb6cfd131d06d50b 100644 --- a/lib/std/fmt/float.zig +++ b/lib/std/fmt/float.zig @@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 { const DT = if (@bitSizeOf(T) <= 64) u64 else u128; const tables = switch (DT) { - u64 => if (@import("builtin").mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, + u64 => if (builtin.mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, u128 => &Backend128_Tables, else => unreachable, }; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index fc613ccdaa313d46dab643f849149293f422a9a5..e9c2d5f8f8e167b7556ec5eaec20d994cc2f5d73 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -2205,7 +2205,7 @@ test "'.' and '..' in absolute functions" { } test "chmod" { - if (native_os == .windows or native_os == .wasi) return; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; @@ -2228,8 +2228,7 @@ test "chmod" { } test "change ownership" { - if (native_os == .windows or native_os == .wasi) - return error.SkipZigTest; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 3964ad5f946f899a51cbfdefb38cb42d2973b74d..1cb8e93092ec55534810432e78e896d88ffa881a 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 { test "typeContainsSlice" { comptime { - try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type))); + try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type))); try testing.expect(typeContainsSlice([]const u8)); try testing.expect(!typeContainsSlice(u8)); diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig index 27f2701443cc919a9cd2686165ecc8ae087ae002..72c8bff280548134abcb34a71857c7c101683dae 100644 --- a/lib/std/hash/xxhash.zig +++ b/lib/std/hash/xxhash.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const mem = std.mem; const expectEqual = std.testing.expectEqual; @@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64) } test "xxhash3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const H = XxHash3; // Non-Seeded Tests try testExpect(H, 0, "", 0x2d06800538d394c2); @@ -820,7 +818,6 @@ test "xxhash3" { } test "xxhash3 smhasher" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405); @@ -832,7 +829,6 @@ test "xxhash3 smhasher" { } test "xxhash3 iterative api" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try verify.iterativeApi(XxHash3); diff --git a/lib/std/math.zig b/lib/std/math.zig index 0beb62ae6a9eb10cdb78e887f900bebcde0612f4..ae644d6fceff795c5cb1864acada365867a19521 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { } test lerp { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5)); diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 485ae4918cce7545119b5b014f7c8133656aaf0b..271041e761a1d6f089c7733aa2964913c771dc0d 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -1,5 +1,4 @@ const std = @import("../../std.zig"); -const builtin = @import("builtin"); const mem = std.mem; const testing = std.testing; const Managed = std.math.big.int.Managed; @@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void { try expectNormalized(1 << 10, res.toConst()); } test setFloat { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try setFloat(f16); try setFloat(f32); try setFloat(f64); @@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void { ); } test toFloat { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; try toFloat(f16); try toFloat(f32); try toFloat(f64); @@ -1391,8 +1387,6 @@ test "mul multi-single" { } test "mul multi-multi" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" { } test "mulWrap multi-multi unsigned" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" { } test "mulWrap multi-multi signed" { - switch (builtin.zig_backend) { - .stage2_c => return error.SkipZigTest, - else => {}, - } - var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1); defer a.deinit(); var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb)); @@ -1744,8 +1731,6 @@ test "div q=0 alias" { } test "div multi-multi q < r" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const op1 = 0x1ffffffff0078f432; const op2 = 0x1ffffffff01000000; var a = try Managed.initSet(testing.allocator, op1); @@ -2166,8 +2151,6 @@ test "div ceil multi-limb" { } test "div multi-multi with rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2184,8 +2167,6 @@ test "div multi-multi with rem" { } test "div multi-multi no rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2202,8 +2183,6 @@ test "div multi-multi no rem" { } test "div multi-multi (2 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333); @@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" { } test "div multi-multi (3.1/3.3 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171); @@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" { } test "div multi-single zero-limb trailing" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x10000000000000000); @@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" { } test "div multi-multi zero-limb trailing (with rem)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" { } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2300,8 +2271,6 @@ test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000); @@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" { } test "bitNotWrap more than two limbs" { - // This test requires int sizes greater than 128 bits. - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - var a = try Managed.initSet(testing.allocator, maxInt(Limb)); defer a.deinit(); @@ -3179,8 +3144,6 @@ test "gcd non-one large" { } test "gcd large multi-limb result" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567); @@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" { var buffer1 = try testing.allocator.alloc(u8, 64); defer testing.allocator.free(buffer1); - const endians = [_]std.builtin.Endian{ .little, .big }; + const endians = [_]std.lang.Endian{ .little, .big }; const abi_size = 64; for (endians) |endian| { diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig index a46948cac54dddf2dd7a822a68188f219086a9af..0dc5b2a8be90cd88276ec344c9de51a492b6430a 100644 --- a/lib/std/math/log10.zig +++ b/lib/std/math/log10.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const testing = std.testing; /// Returns the base-10 logarithm of x. @@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 { } test log10_int { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - inline for ( .{ u8, u16, u32, u64, u128, u256, u512 }, .{ 2, 4, 9, 19, 38, 77, 154 }, diff --git a/lib/std/math/signbit.zig b/lib/std/math/signbit.zig index 115aaa26eb056e31c423695cd2a2cde79050d0a1..36a933e641ce35985523b25bb403f234143c20bc 100644 --- a/lib/std/math/signbit.zig +++ b/lib/std/math/signbit.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8353c0ca8e209dd1516371926e0fbfd00f874ded..9529f73b93586014b6338eef2ecd780461b9cd37 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4780,62 +4780,47 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize { pub fn doNotOptimizeAway(val: anytype) void { if (@inComptime()) return; + if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) { + _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct { + var escape: *const anyopaque = undefined; + }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded") + return; + } + const max_gp_register_bits = @bitSizeOf(c_long); - const t = @typeInfo(@TypeOf(val)); - switch (t) { + switch (@typeInfo(@TypeOf(val))) { .void, .null, .comptime_int, .comptime_float => return, .@"enum" => doNotOptimizeAway(@backingInt(val)), .bool => doNotOptimizeAway(@intFromBool(val)), - .int => { - const bits = t.int.bits; - if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) { - const val2 = @as( - @Int(t.int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))), - val, - ); - asm volatile ("" - : - : [_] "r" (val2), - ); - } else doNotOptimizeAway(&val); - }, - .float => { - if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) { - asm volatile ("" - : - : [_] "rm" (val), - ); - } else doNotOptimizeAway(&val); - }, - .pointer => { - if (builtin.zig_backend == .stage2_c) { - doNotOptimizeAwayC(val); - } else { - asm volatile ("" - : - : [_] "m" (val), - : .{ .memory = true }); - } - }, - .array => { - if (t.array.len * @sizeOf(t.array.child) <= 64) { - for (val) |v| doNotOptimizeAway(v); - } else doNotOptimizeAway(&val); + .int => |int| if (int.bits <= max_gp_register_bits) { + const val2 = @as( + @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))), + val, + ); + asm volatile ("" + : + : [_] "r" (val2), + ); + } else doNotOptimizeAway(&val), + .float => |float| switch (float.bits) { + else => comptime unreachable, + 16, 80, 128 => doNotOptimizeAway(&val), + 32, 64 => asm volatile ("" + : + : [_] "rm" (val), + ), }, + .pointer => asm volatile ("" + : + : [_] "m" (val), + : .{ .memory = true }), + .array => |array| if (array.len * @sizeOf(array.child) <= 64) { + for (val) |v| doNotOptimizeAway(v); + } else doNotOptimizeAway(&val), else => doNotOptimizeAway(&val), } } -/// .stage2_c doesn't support asm blocks yet, so use volatile stores instead -var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined; -fn doNotOptimizeAwayC(ptr: anytype) void { - const dest = @as(*volatile u8, @ptrCast(&deopt_target)); - for (asBytes(ptr)) |b| { - dest.* = b; - } - dest.* = 0; -} - test doNotOptimizeAway { comptime doNotOptimizeAway("test"); @@ -4994,12 +4979,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice } test "read/write(Var)PackedInt" { - switch (builtin.cpu.arch) { - // This test generates too much code to execute on WASI. - // LLVM backend fails with "too many locals: locals exceed maximum" - .wasm32, .wasm64 => return error.SkipZigTest, - else => {}, - } + // This test generates too much code to execute on WASI. + // LLVM backend fails with "too many locals: locals exceed maximum" + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; const foreign_endian: Endian = if (native_endian == .big) .little else .big; const expect = std.testing.expect; diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index a49c1d48bedd05331da4a7a25c6f1006797aa251..431097feccf104eba84a3f347fac6fe29ae1eb57 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -154,7 +154,7 @@ pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { switch (builtin.zig_backend) { .stage2_c => asm volatile ( - \\ mov x8, %[number] + \\ mov w8, %[number] \\ svc #0 : : [number] "i" (@backingInt(SYS.rt_sigreturn)), diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 9b9ca0cd0327c93c1260128f42a497e8d96a3094..3c44beeb8df7bb5d7f0d7d7fb13f3c35c840da01 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 { } pub fn restore() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.sigreturn)), + ), + } } pub fn restore_rt() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.rt_sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), + ), + } } pub const time_t = i64; diff --git a/lib/std/testing/Smith.zig b/lib/std/testing/Smith.zig index 7e3235fe0e5ffd1163a2cc7bf46f7583eb0a06ae..a60a9802391078fe6ca400fb4409216bd73ff345 100644 --- a/lib/std/testing/Smith.zig +++ b/lib/std/testing/Smith.zig @@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) { } test value { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { v: void = {}, diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index b22de08eacccf9c75e24a6f32e85ce7d795e12a8..16294f3df6d763df2587b48fbb99e3b6615d478f 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -9,7 +9,6 @@ //! For lower level control over parsing, see `std.zig.Zoir`. const std = @import("std"); -const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const Ast = std.zig.Ast; const Zoir = std.zig.Zoir; @@ -1868,8 +1867,6 @@ test "std.zon tuples" { // Test sizes 0 to 3 since small sizes get parsed differently test "std.zon arrays and slices" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881 - const gpa = std.testing.allocator; // Literals @@ -2802,8 +2799,6 @@ test "std.zon negative char" { } test "std.zon parse float" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - const gpa = std.testing.allocator; // Test decimals @@ -3135,7 +3130,7 @@ test "std.zon free on error" { } test "std.zon vector" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330 + const builtin = @import("builtin"); if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957 const gpa = std.testing.allocator; diff --git a/lib/std/zon/stringify.zig b/lib/std/zon/stringify.zig index 57b62d41cac6c3f9aa0e442bd276edb33f2679c2..a1c6b39ebe25a350d08eba57008fbd3522c16f76 100644 --- a/lib/std/zon/stringify.zig +++ b/lib/std/zon/stringify.zig @@ -1151,9 +1151,6 @@ test "std.zon depth limits" { } test "std.zon stringify primitives" { - // Issue: https://github.com/ziglang/zig/issues/20880 - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - try expectSerializeEqual( \\.{ \\ .a = 1.5, diff --git a/lib/zig.h b/lib/zig.h index fc2f9479bea2bf9599dfcaebe35294fed98b4db4..139263d11132833d2c64539c2b39cf44b3bd0b89 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -166,6 +166,12 @@ #endif #define zig_expand_has_builtin(b) zig_has_builtin(b) +#if defined(__has_feature) +#define zig_has_feature(feature) __has_feature(feature) +#else +#define zig_has_feature(feature) 0 +#endif + #if defined(__has_attribute) #define zig_has_attribute(attribute) __has_attribute(attribute) #else @@ -175,9 +181,9 @@ #if __STDC_VERSION__ >= 201112L #define zig_static_assert(cond, msg) _Static_assert(cond, msg) #elif zig_has_attribute(unused) -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused)) #else -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] #endif #if __STDC_VERSION__ >= 202311L @@ -267,12 +273,20 @@ #if __STDC_VERSION__ >= 202311L #define zig_align(alignment) alignas(alignment) -#elif __STDC_VERSION__ >= 201112L +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) #define zig_align(alignment) _Alignas(alignment) #else #define zig_align(alignment) zig_under_align(alignment) #endif +#if __STDC_VERSION__ >= 202311L +#define zig_alignOf(Type) alignof(Type) +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof) +#define zig_alignOf(Type) _Alignof(Type) +#else +#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type)) +#endif + #if zig_has_attribute(aligned) || defined(zig_tinyc) #define zig_align_fn(alignment) __attribute__((aligned(alignment))) #elif defined(zig_msvc) @@ -350,11 +364,9 @@ #define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ - __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) + __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol)) #endif -#define zig_mangled_tentative zig_mangled -#define zig_mangled_final zig_mangled #if defined(zig_msvc) #define zig_mangled(mangled, unmangled) ; \ zig_export(#mangled, unmangled) @@ -364,7 +376,7 @@ #else /* zig_msvc */ #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) #define zig_mangled_export(mangled, unmangled, symbol) \ - zig_mangled_final(mangled, unmangled) \ + zig_mangled(mangled, unmangled) \ zig_export(symbol, unmangled) #endif /* zig_msvc */ @@ -550,6 +562,9 @@ #define zig_noreturn #endif +#define zig_has_always 1 +#define zig_has_never 0 + #define zig_compiler_rt_abbrev_uint32_t si #define zig_compiler_rt_abbrev_int32_t si #define zig_compiler_rt_abbrev_uint64_t di @@ -560,7 +575,11 @@ #define zig_compiler_rt_abbrev_zig_f32 sf #define zig_compiler_rt_abbrev_zig_f64 df #define zig_compiler_rt_abbrev_zig_f80 xf +#ifdef zig_powerpc +#define zig_compiler_rt_abbrev_zig_f128 kf +#else #define zig_compiler_rt_abbrev_zig_f128 tf +#endif zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); @@ -645,16 +664,6 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) -#if defined(zig_ez80) -typedef unsigned int uint24_t; -typedef signed int int24_t; -#define INT24_C(c) c -#define UINT24_C(c) c##U -#endif -#define INT24_MIN (~INT24_C(0x7FFF)) -#define INT24_MAX ( INT24_C(0x7FFF)) -#define UINT24_MAX ( INT24_C(0xFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -685,17 +694,6 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) -#if defined(zig_ez80) -typedef unsigned __int48 uint48_t; -typedef signed __int48 int48_t; -#define INT48_C(c) c -/* no suffix */ -#define UINT48_C(c) ((uint48_t)(c)) -#endif -#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) -#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) -#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -726,6 +724,27 @@ typedef signed long long int64_t; #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) +#if defined(zig_ez80) + +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + +#endif + typedef size_t uintptr_t; typedef ptrdiff_t intptr_t; @@ -739,23 +758,145 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX -#define zig_minInt_i24 INT24_MIN -#define zig_maxInt_i24 INT24_MAX -#define zig_minInt_u24 UINT24_C(0) -#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX -#define zig_minInt_i48 INT48_MIN -#define zig_maxInt_i48 INT48_MAX -#define zig_minInt_u48 UINT48_C(0) -#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) #define zig_maxInt_u64 UINT64_MAX +// zig_promoted_T implements C integral promotions except with signedness preserved, which +// allows wrapping operations to avoid the ub that would be caused by the normal promotion. + +#if INT8_MAX <= INT_MAX +typedef unsigned int zig_promoted_i8; +#elif INT8_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i8; +#elif INT8_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i8; +#else +typedef int8_t zig_promoted_i8; +#endif +#if UINT8_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u8; +#elif UINT8_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u8; +#elif UINT8_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u8; +#else +typedef uint8_t zig_promoted_u8; +#endif + +#if INT16_MAX <= INT_MAX +typedef unsigned int zig_promoted_i16; +#elif INT16_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i16; +#elif INT16_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i16; +#else +typedef int16_t zig_promoted_i16; +#endif +#if UINT16_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u16; +#elif UINT16_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u16; +#elif UINT16_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u16; +#else +typedef uint16_t zig_promoted_u16; +#endif + +#if INT32_MAX <= INT_MAX +typedef unsigned int zig_promoted_i32; +#elif INT32_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i32; +#elif INT32_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i32; +#else +typedef int32_t zig_promoted_i32; +#endif +#if UINT32_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u32; +#elif UINT32_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u32; +#elif UINT32_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u32; +#else +typedef uint32_t zig_promoted_u32; +#endif + +#if INT64_MAX <= INT_MAX +typedef unsigned int zig_promoted_i64; +#elif INT64_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i64; +#elif INT64_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i64; +#else +typedef int64_t zig_promoted_i64; +#endif +#if UINT64_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u64; +#elif UINT64_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u64; +#elif UINT64_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u64; +#else +typedef uint64_t zig_promoted_u64; +#endif + +#ifdef zig_ez80 + +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX + +#if INT24_MAX <= INT_MAX +typedef unsigned int zig_promoted_i24; +#elif INT24_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i24; +#elif INT24_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i24; +#else +typedef int24_t zig_promoted_i24; +#endif +#if UINT24_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u24; +#elif UINT24_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u24; +#elif UINT24_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u24; +#else +typedef uint24_t zig_promoted_u24; +#endif + +#if INT48_MAX <= INT_MAX +typedef unsigned int zig_promoted_i48; +#elif INT48_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i48; +#elif INT48_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i48; +#else +typedef int48_t zig_promoted_i48; +#endif +#if UINT48_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u48; +#elif UINT48_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u48; +#elif UINT48_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u48; +#else +typedef uint48_t zig_promoted_u48; +#endif + +#endif + #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) @@ -770,7 +911,33 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w, PromotedUnsigned) \ + +#define zig_int_casts_common(bw, sw) \ + static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \ + return (uint##bw##_t)arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \ + return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \ + } \ +\ + static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \ + return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \ + ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \ + } +#define zig_int_operators(w) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -786,44 +953,48 @@ typedef ptrdiff_t intptr_t; return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \ } \ \ - static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \ - return val ^ zig_maxInt_u(w, bits); \ + static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ + return arg ^ zig_maxInt_u(w, bits); \ } \ \ - static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \ + static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \ (void)bits; \ - return ~val; \ + return ~arg; \ } \ \ - static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \ - return val & zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ - return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ - ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ - } \ -\ - static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ - return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ - } \ -\ - zig_basic_operator(uint##w##_t, div_floor_u##w, /) \ + zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ \ - static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ } \ \ - static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ } \ \ - static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ } \ \ zig_basic_operator(uint##w##_t, mod_u##w, %) \ + zig_int_casts_common(w, w) \ +\ + static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w(arg, bits); \ + } \ +\ + static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w(arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \ + } \ \ static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ int##w##_t rem = lhs % rhs; \ @@ -831,100 +1002,102 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \ + return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \ } \ \ static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \ } \ \ static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs + rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \ } \ \ static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs - rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \ } \ \ static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ + } \ +\ + static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \ + int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \ + return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \ + } \ +\ + static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ } -#if UINT8_MAX <= UINT_MAX -zig_int_helpers(8, unsigned int) -#elif UINT8_MAX <= ULONG_MAX -zig_int_helpers(8, unsigned long) -#elif UINT8_MAX <= ULLONG_MAX -zig_int_helpers(8, unsigned long long) -#else -zig_int_helpers(8, uint8_t) +zig_int_operators(8) +zig_int_operators(16) +zig_int_operators(32) +zig_int_operators(64) +#ifdef zig_ez80 +zig_int_operators(24) +zig_int_operators(48) #endif -#if UINT16_MAX <= UINT_MAX -zig_int_helpers(16, unsigned int) -#elif UINT16_MAX <= ULONG_MAX -zig_int_helpers(16, unsigned long) -#elif UINT16_MAX <= ULLONG_MAX -zig_int_helpers(16, unsigned long long) -#else -zig_int_helpers(16, uint16_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(24, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(24, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(24, unsigned long long) -#else -zig_int_helpers(24, uint24_t) -#endif -#endif -#if UINT32_MAX <= UINT_MAX -zig_int_helpers(32, unsigned int) -#elif UINT32_MAX <= ULONG_MAX -zig_int_helpers(32, unsigned long) -#elif UINT32_MAX <= ULLONG_MAX -zig_int_helpers(32, unsigned long long) -#else -zig_int_helpers(32, uint32_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(48, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(48, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(48, unsigned long long) -#else -zig_int_helpers(48, uint48_t) -#endif -#endif -#if UINT64_MAX <= UINT_MAX -zig_int_helpers(64, unsigned int) -#elif UINT64_MAX <= ULONG_MAX -zig_int_helpers(64, unsigned long) -#elif UINT64_MAX <= ULLONG_MAX -zig_int_helpers(64, unsigned long long) -#else -zig_int_helpers(64, uint64_t) + +#define zig_int_casts(bw, sw) \ + static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + zig_int_casts_common(bw, sw) +zig_int_casts(16, 8) +zig_int_casts(32, 8) +zig_int_casts(64, 8) +zig_int_casts(32, 16) +zig_int_casts(64, 16) +zig_int_casts(64, 32) +#ifdef zig_ez80 +zig_int_casts(32, 24) +zig_int_casts(48, 24) +zig_int_casts(64, 24) +zig_int_casts(64, 48) #endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_addw_u32(lhs, rhs, bits); @@ -936,19 +1109,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i32(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_addw_u64(lhs, rhs, bits); @@ -960,24 +1133,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i64(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -986,12 +1159,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1000,12 +1173,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1014,27 +1187,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1043,28 +1217,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1073,22 +1245,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_subw_u32(lhs, rhs, bits); @@ -1100,20 +1273,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i32(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_subw_u64(lhs, rhs, bits); @@ -1125,24 +1297,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i64(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1151,12 +1323,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1165,12 +1337,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1179,27 +1351,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1208,28 +1381,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1238,22 +1409,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_mulw_u32(lhs, rhs, bits); @@ -1261,8 +1433,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { + zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1271,7 +1443,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i32(full_res, bits); + *res = zig_i32_truncate_i32(full_res, bits); return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } @@ -1279,7 +1451,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_mulw_u64(lhs, rhs, bits); @@ -1287,8 +1459,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { + zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1297,7 +1469,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i64(full_res, bits); + *res = zig_i64_truncate_i64(full_res, bits); return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } @@ -1305,12 +1477,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1319,12 +1491,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1333,12 +1505,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1347,27 +1519,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1376,28 +1549,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1406,18 +1577,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif -#define zig_int_builtins(w) \ +#define zig_shls_builtins(lw, rw) \ + static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + uint##lw##_t res; \ + if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \ + } \ +\ + static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + int##lw##_t res; \ + if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \ + lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \ + } +#define zig_int_sat_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ return lhs > zig_maxInt_u(w, bits) >> rhs; \ @@ -1429,18 +1614,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \ } \ \ - static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - uint##w##_t res; \ - if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - int##w##_t res; \ - if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ - lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ - } \ + zig_shls_builtins(w, 8) \ + zig_shls_builtins(w, 16) \ + zig_shls_builtins(w, 32) \ + zig_shls_builtins(w, 64) \ \ static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ uint##w##_t res; \ @@ -1474,332 +1651,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ } -zig_int_builtins(8) -zig_int_builtins(16) +zig_int_sat_builtins(8) +zig_int_sat_builtins(16) +zig_int_sat_builtins(32) +zig_int_sat_builtins(64) #if defined(zig_ez80) -zig_int_builtins(24) +zig_int_sat_builtins(24) +zig_int_sat_builtins(48) #endif -zig_int_builtins(32) -#if defined(zig_ez80) -zig_int_builtins(48) -#endif -zig_int_builtins(64) -#define zig_builtin8(name, val) __builtin_##name(val) +#define zig_builtin8(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin8; -#define zig_builtin16(name, val) __builtin_##name(val) +#define zig_builtin16(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin16; -#if defined(zig_ez80) -#define zig_builtin24(name, val) __builtin_##name(val) -typedef unsigned int zig_Builtin24; -#endif - #if INT_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name(val) +#define zig_builtin32(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin32; #elif LONG_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name##l(val) +#define zig_builtin32(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin32; #endif -#if defined(zig_ez80) -#define zig_builtin48(name, val) __builtin_##name(val) -typedef unsigned long long zig_Builtin48; -#endif - #if INT_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name(val) +#define zig_builtin64(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin64; #elif LONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##l(val) +#define zig_builtin64(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin64; #elif LLONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##ll(val) +#define zig_builtin64(name, arg) __builtin_##name##ll(arg) typedef unsigned long long zig_Builtin64; #endif -static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { - return zig_wrap_u8(val >> (8 - bits), bits); +#if defined(zig_ez80) +#define zig_builtin24(name, arg) __builtin_##name(arg) +typedef unsigned int zig_Builtin24; +#define zig_builtin48(name, arg) __builtin_##name(arg) +typedef unsigned long long zig_Builtin48; +#endif + +static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { + return zig_u8_truncate_u8(arg >> (8 - bits), bits); } -static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); +static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bswap16) || defined(zig_gcc) - full_res = __builtin_bswap16(val); + full_res = __builtin_bswap16(arg); #else - full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); +static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bswap24) || defined(zig_gcc) - full_res = __builtin_bswap24(val); + full_res = __builtin_bswap24(arg); #else - full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) - full_res = __builtin_bswap32(val); + full_res = __builtin_bswap32(arg); #else - full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); +static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bswap48) || defined(zig_gcc) - full_res = __builtin_bswap48(val); + full_res = __builtin_bswap48(arg); #else - full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u48(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) - full_res = __builtin_bswap64(val); + full_res = __builtin_bswap64(arg); #else - full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); +static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); } -static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { +static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { uint8_t full_res; #if zig_has_builtin(bitreverse8) - full_res = __builtin_bitreverse8(val); + full_res = __builtin_bitreverse8(arg); #else static uint8_t const lut[0x10] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0; + full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0; #endif - return zig_wrap_u8(full_res >> (8 - bits), bits); + return zig_u8_truncate_u8(full_res >> (8 - bits), bits); } -static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); +static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bitreverse16) - full_res = __builtin_bitreverse16(val); + full_res = __builtin_bitreverse16(arg); #else - full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); +static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { +static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bitreverse24) - full_res = __builtin_bitreverse24(val); + full_res = __builtin_bitreverse24(arg); #else - full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) - full_res = __builtin_bitreverse32(val); + full_res = __builtin_bitreverse32(arg); #else - full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); +static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bitreverse48) - full_res = __builtin_bitreverse48(val); + full_res = __builtin_bitreverse48(arg); #else - full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u32(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) - full_res = __builtin_bitreverse64(val); + full_res = __builtin_bitreverse64(arg); #else - full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); +static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); } -#define zig_builtin_popcount_common(w) \ - static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w((uint##w##_t)val, bits); \ +#define zig_builtin_popCount_common(w) \ + static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w((uint##w##_t)arg, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - return zig_builtin##w(popcount, val); \ + return zig_builtin##w(popcount, arg); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #else -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \ + uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \ temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #endif -zig_builtin_popcount(8) -zig_builtin_popcount(16) +zig_builtin_popCount(8) +zig_builtin_popCount(16) +zig_builtin_popCount(32) +zig_builtin_popCount(64) #if defined(zig_ez80) -zig_builtin_popcount(24) +zig_builtin_popCount(24) +zig_builtin_popCount(48) #endif -zig_builtin_popcount(32) -#if defined(zig_ez80) -zig_builtin_popcount(48) -#endif -zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ - static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(ctz, val); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(ctz, arg); \ } \ \ zig_builtin_ctz_common(w) #else #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ } \ \ zig_builtin_ctz_common(w) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) -#if defined(zig_ez80) -zig_builtin_ctz(24) -#endif zig_builtin_ctz(32) -#if defined(zig_ez80) -zig_builtin_ctz(48) -#endif zig_builtin_ctz(64) +#if defined(zig_ez80) +zig_builtin_ctz(24) +zig_builtin_ctz(48) +#endif #define zig_builtin_clz_common(w) \ - static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_clz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_clz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ } \ \ zig_builtin_clz_common(w) #else #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ } \ \ zig_builtin_clz_common(w) #endif zig_builtin_clz(8) zig_builtin_clz(16) -#if defined(zig_ez80) -zig_builtin_clz(24) -#endif zig_builtin_clz(32) -#if defined(zig_ez80) -zig_builtin_clz(48) -#endif zig_builtin_clz(64) +#if defined(zig_ez80) +zig_builtin_clz(24) +zig_builtin_clz(48) +#endif /* ======================== 128-bit Integer Support ========================= */ @@ -1816,16 +1982,14 @@ zig_builtin_clz(64) typedef unsigned __int128 zig_u128; typedef signed __int128 zig_i128; -#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) -#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#define zig_hi_u128(val) ((uint64_t)((val) >> 64)) -#define zig_lo_u128(val) ((uint64_t)((val) >> 0)) -#define zig_hi_i128(val) (( int64_t)((val) >> 64)) -#define zig_lo_i128(val) ((uint64_t)((val) >> 0)) -#define zig_bitCast_u128(val) ((zig_u128)(val)) -#define zig_bitCast_i128(val) ((zig_i128)(val)) +#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) +#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) +#define zig_make_u128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) zig_init_i128(hi, lo) +#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) +#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) +#define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) +#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs > rhs) - (lhs < rhs); \ @@ -1835,32 +1999,49 @@ typedef signed __int128 zig_i128; return lhs operator rhs; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + return lhs >> rhs; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif +} + #else /* zig_has_int128 */ #if zig_little_endian -typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; -typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; #else -typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; -typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; #endif -#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) -#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) - -#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#endif -#define zig_hi_u128(val) ((val).hi) -#define zig_lo_u128(val) ((val).lo) -#define zig_hi_i128(val) ((val).hi) -#define zig_lo_i128(val) ((val).lo) -#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) -#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) +#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) +#define zig_hi_u128(arg) (arg).hi +#define zig_lo_u128(arg) (arg).lo +#define zig_hi_i128(arg) (arg).hi +#define zig_lo_i128(arg) (arg).lo #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs.hi == rhs.hi) \ @@ -1872,6 +2053,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; + return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + #endif /* zig_has_int128 */ #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) @@ -1891,42 +2096,177 @@ zig_bit_int128(i128, or, |) zig_bit_int128(u128, xor, ^) zig_bit_int128(i128, xor, ^) -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); +static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { + return (uint8_t)zig_lo_u128(arg); +} +static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { + return (uint8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { + return (int8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { + return (int8_t)zig_lo_u128(arg); +} -#if zig_has_int128 +static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { + return (uint16_t)zig_lo_u128(arg); +} +static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { + return (uint16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { + return (int16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { + return (int16_t)zig_lo_u128(arg); +} -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return val ^ zig_maxInt_u(128, bits); +static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { + return (uint32_t)zig_lo_u128(arg); +} +static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { + return (uint32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { + return (int32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { + return (int32_t)zig_lo_u128(arg); } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - (void)bits; - return ~val; +static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { + return zig_lo_u128(arg); +} +static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { + return zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { + return (int64_t)zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { + return (int64_t)zig_lo_u128(arg); +} + +static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { + return zig_make_u128(UINT8_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { + return zig_make_u128(UINT8_C(0), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { + return zig_make_i128(INT8_C(0), arg); } -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { + return zig_make_u128(UINT16_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { + return zig_make_u128(UINT16_C(0), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { + return zig_make_i128(INT16_C(0), arg); } -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - return lhs << rhs; +static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { + return zig_make_u128(UINT32_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { + return zig_make_u128(UINT32_C(0), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { + return zig_make_i128(INT32_C(0), arg); } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - // This works around a GCC miscompilation, but it has the side benefit of - // emitting better code. It is behind the `#if` because it depends on - // arithmetic right shift, which is implementation-defined in C, but should - // be guaranteed on any GCC-compatible compiler. -#if defined(zig_gnuc) - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { + return zig_make_u128(UINT64_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { + return zig_make_u128(UINT64_C(0), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { + return zig_make_i128(INT64_C(0), arg); +} + +static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { + return arg; +} +static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { +#if zig_has_int128 + return (zig_u128)arg; +#else + return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); +#endif +} +static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { + return arg; +} +static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) { +#if zig_has_int128 + return (zig_i128)arg; #else - zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); - return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; + return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); #endif } -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - return lhs << rhs; +#define zig_int128_cast_builtins(w) \ + static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ + } +zig_int128_cast_builtins(8) +zig_int128_cast_builtins(16) +zig_int128_cast_builtins(32) +zig_int128_cast_builtins(64) + +static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) { + return zig_and_u128(arg, zig_maxInt_u(128, bits)); +} +static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) { + if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg)); + int64_t lo = zig_i64_truncate_i128(arg, bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); +} + +static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) { + return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits); +} +static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) { + return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits); +} + +#if zig_has_int128 + +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + return arg ^ zig_maxInt_u(128, bits); +} + +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return ~arg; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -1953,11 +2293,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return lhs * rhs; } -static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { return lhs / rhs; } -static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { return lhs / rhs; } @@ -1971,36 +2311,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { #else /* zig_has_int128 */ -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; + return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; -} - -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; - return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; -} - -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; -} - -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; - return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; -} - -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -2027,59 +2345,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { return res; } -zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); return __multi3(lhs, rhs); } static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs))); + return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128)); } -zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); -static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); return __udivti3(lhs, rhs); } -zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); -static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); return __divti3(lhs, rhs); } -zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); return __umodti3(lhs, rhs); } -zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); return __modti3(lhs, rhs); } #endif /* zig_has_int128 */ -#define zig_div_floor_u128 zig_div_trunc_u128 +#define zig_divFloor_u128 zig_divTrunc_u128 -static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); } -static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { zig_u128 rem = zig_rem_u128(lhs, rhs); uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) ? UINT64_C(1) : UINT64_C(0); - return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); + return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); } -static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); } #define zig_mod_u128 zig_rem_u128 @@ -2107,51 +2425,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { - return zig_and_u128(val, zig_maxInt_u(128, bits)); -} - -static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); - int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); - return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); -} - static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits); } static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits); } static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_add_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits); } static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits); } static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits); } static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } -static inline zig_u128 zig_abs_i128(zig_i128 val) { - zig_i128 tmp = zig_shr_i128(val, 127); - return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +static inline zig_u128 zig_abs_i128(zig_i128 arg) { + zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); + return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); } #if zig_has_int128 @@ -2160,7 +2468,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(add_overflow) zig_u128 full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_addw_u128(lhs, rhs, bits); @@ -2176,7 +2484,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2184,7 +2492,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(sub_overflow) zig_u128 full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_subw_u128(lhs, rhs, bits); @@ -2200,7 +2508,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2208,7 +2516,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(mul_overflow) zig_u128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_mulw_u128(lhs, rhs, bits); @@ -2216,8 +2524,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #endif } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); #if zig_has_builtin(mul_overflow) zig_i128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -2226,50 +2534,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } #else /* zig_has_int128 */ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { *res = zig_mulw_u128(lhs, rhs, bits); - return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && - zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); + return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && + zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0 || zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow; } @@ -2282,28 +2618,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { *res = zig_shlw_i128(lhs, rhs, bits); - zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1))); + zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits); return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); } -static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { +#define zig_int128_shls_builtins(rw) \ + static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_u128 res; \ + if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \ + case 0: return zig_minInt_u(128, bits); \ + case 1: return zig_maxInt_u(128, bits); \ + default: zig_unreachable(); \ + } \ + } \ +\ + static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_i128 res; \ + if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \ + case -1: return zig_minInt_i(128, bits); \ + case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \ + case 1: return zig_maxInt_i(128, bits); \ + default: zig_unreachable(); \ + } \ + } +zig_int128_shls_builtins(8) +zig_int128_shls_builtins(16) +zig_int128_shls_builtins(32) +zig_int128_shls_builtins(64) + +static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { - case 0: return zig_make_u128(0, 0); - case 1: return zig_maxInt_u(128, bits); + case INT32_C(0): return zig_make_u128(0, 0); + case INT32_C(1): return zig_maxInt_u(128, bits); default: zig_unreachable(); } } -static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { +static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { zig_i128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { - case -1: return zig_minInt_i(128, bits); - case 0: return zig_make_i128(0, 0); - case 1: return zig_maxInt_i(128, bits); + case -INT32_C(1): return zig_minInt_i(128, bits); + case INT32_C(0): return zig_make_i128(0, 0); + case INT32_C(1): return zig_maxInt_i(128, bits); default: zig_unreachable(); } } @@ -2341,57 +2703,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); } -static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { - if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); - if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); - return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); +static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); + if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); + return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); } -static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { - return zig_clz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { + return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { - if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); - return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); +static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { + if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); + return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); } -static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { - return zig_ctz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { + return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { - return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + - zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); +static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { + return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + + zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); } -static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { - return zig_popcount_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { + return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { +static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { zig_u128 full_res; #if zig_has_builtin(bswap128) - full_res = __builtin_bswap128(val); + full_res = __builtin_bswap128(arg); #else - full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), - zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); + full_res = zig_make_u128( + zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) + ); #endif return zig_shr_u128(full_res, UINT8_C(128) - bits); } -static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } -static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { - return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), - zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), - UINT8_C(128) - bits); +static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { + return zig_shr_u128(zig_make_u128( + zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) + ), UINT8_C(128) - bits); } -static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } #if zig_has_int128 @@ -2411,12 +2776,378 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { /* ========================== Big Integer Support =========================== */ static inline uint16_t zig_int_bytes(uint16_t bits) { - uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1); uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; return (bytes + alignment - 1) / alignment * alignment; } +static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_minInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset); +#endif +} + +static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_maxInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_maxInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset); +#endif +} + +static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + + if (!is_signed) return INT8_C(0); +#if zig_little_endian + byte_offset = zig_int_bytes(bits) - 1; +#endif + return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7)); +} + +static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + uint16_t arg_size = zig_int_bytes(arg_bits); + uint16_t copy_size = zig_min_u16(res_size, arg_size); + uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8)); + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], copy_size); + memset(&res_bytes[copy_size], sign_fill, res_size - copy_size); +#else + memset(&res_bytes[0], sign_fill, res_size - copy_size); + memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size); +#endif +} + +static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + + if (res_is_signed != arg_is_signed) zig_unreachable(); + if (res_bits > arg_bits) zig_unreachable(); + + if (res_is_signed) { + uint16_t arg_byte_offset = UINT16_C(0); + +#if zig_big_endian + arg_byte_offset = zig_int_bytes(arg_bits) - res_size; +#endif + + memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size); + } else { + uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3)); + uint16_t arg_byte_offset = res_byte_offset; + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset); +#else + res_byte_offset = res_size - UINT16_C(1) - res_byte_offset; + arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset; + + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + + res_bytes[res_byte_offset] = zig_u8_truncate_u8( + arg_bytes[arg_byte_offset], + zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1) + ); + res_byte_offset += UINT16_C(1); + arg_byte_offset += UINT16_C(1); + +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset); +#else + memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset); +#endif + } +} + +#define zig_big_casts(is, s, w, IntType) \ + static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \ + } \ +\ + static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \ + } +zig_big_casts(false, u, 8, uint8_t) +zig_big_casts(true , i, 8, int8_t) +zig_big_casts(false, u, 16, uint16_t) +zig_big_casts(true , i, 16, int16_t) +zig_big_casts(false, u, 32, uint32_t) +zig_big_casts(true , i, 32, int32_t) +zig_big_casts(false, u, 64, uint64_t) +zig_big_casts(true , i, 64, int64_t) +zig_big_casts(false, u, 128, zig_u128) +zig_big_casts(true , i, 128, zig_i128) + +static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + +#if zig_big_endian + byte_offset = size - UINT16_C(1) - byte_offset; +#endif + + if (res_is_signed) { + int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset); +#endif +} + +static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int16_t lhs_cmp_limb; + int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); + if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb = rhs_byte; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; @@ -2579,6 +3310,168 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign return 0; } +static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes != 128 / CHAR_BIT || is_signed) { + zig_i128 res_limb; + zig_i128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes != 64 / CHAR_BIT || is_signed) { + int64_t res_limb; + int64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes != 32 / CHAR_BIT || is_signed) { + int32_t res_limb; + int32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes != 16 / CHAR_BIT || is_signed) { + int16_t res_limb; + int16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes != 8 / CHAR_BIT || is_signed) { + int8_t res_limb; + int8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; @@ -2816,13 +3709,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool } } +static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) { + memcpy(res, arg, remaining_bytes); + return; + } + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool overflow = true; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + +static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3038,7 +4333,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3248,323 +4543,755 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo return overflow; } +static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_addo_big(res, lhs, rhs, is_signed, bits); } +static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits); + + if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } +} + +static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_subo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __udivei4(res, lhs, rhs, bits); - return; - } +static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1); - zig_trap(); + if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } } -static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_div_trunc_big(res, lhs, rhs, is_signed, bits); - return; +static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t size = zig_int_bytes(bits); + uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8)); + uint16_t lhs_byte_offset = sign_byte_offset; + uint16_t lhs_end_byte_offset = UINT16_C(0); + bool overflow = false; + +#if zig_big_endian + lhs_byte_offset = size - lhs_byte_offset; + lhs_end_byte_offset = size - lhs_end_byte_offset; +#endif + + while (lhs_byte_offset != lhs_end_byte_offset) { + uint16_t rhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint16_t res_byte_offset; + uint16_t lhs_byte; + uint8_t res_byte = UINT8_C(0); + uint16_t mul_res = UINT16_C(0); + uint8_t carry = UINT8_C(0); + +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#else + rhs_byte_offset = size - rhs_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + + lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill; + +#if zig_big_endian + lhs_byte_offset += UINT16_C(1); +#endif + + res_byte_offset = lhs_byte_offset; + + while (res_byte_offset != end_byte_offset) { + bool res_byte_initialized = res_byte_offset != lhs_byte_offset; + +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); + res_byte_offset -= UINT16_C(1); +#endif + + if (res_byte_initialized) res_byte = res_bytes[res_byte_offset]; + carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8)); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16( + zig_shr_u16(mul_res, UINT8_C(8)) + ), UINT8_C(8)); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); + res_byte_offset += UINT16_C(1); +#endif + } + + while (rhs_byte_offset != end_byte_offset) { +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); +#endif + + carry = zig_addo_u8( + &res_byte, + zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))), + carry, + UINT8_C(8) + ); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + overflow |= res_byte != UINT8_C(0); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); +#endif + } + + overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0); + overflow |= carry != UINT8_C(0); } - zig_trap(); +#if zig_little_endian + sign_byte_offset -= UINT64_C(1); +#else + sign_byte_offset = size - sign_byte_offset; +#endif + + if (lhs_sign_fill != rhs_sign_fill) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(0); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8( + &res_bytes[byte_offset], + res_byte, + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (lhs_sign_fill != UINT8_C(0)) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(1); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8)); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + lhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + rhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (is_signed) { + int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + + overflow |= signed_res_byte < INT8_C(0); + } + + { + uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t fill_byte = UINT8_C(0); + + if (is_signed) { + int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + } else { + uint8_t sign_byte = res_bytes[sign_byte_offset]; + uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = truncated; + } + +#if zig_little_endian + sign_byte_offset += UINT16_C(1); + memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset); +#else + memset(&res_bytes[0], fill_byte, sign_byte_offset); +#endif + } + + return overflow; +} + +static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow } -static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - zig_trap(); +static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_mulo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __umodei4(res, lhs, rhs, bits); - return; +static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits); + + if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); } +} + +static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __divei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __udivei5(res, lhs, rhs, temp, bits); + } +} - zig_trap(); +static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __modei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __umodei5(res, lhs, rhs, temp, bits); + } } -static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_rem_big(res, lhs, rhs, is_signed, bits); - return; +static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool decrement = false; + + if (is_signed) { + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + decrement = zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32)); } + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (decrement) zig_decrement_big(res, is_signed, bits); +} - zig_trap(); +static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool increment = false; + + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + increment = zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ) > INT32_C(0); + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (increment) zig_increment_big(res, is_signed, bits); } -static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t skip_bits = remaining_bytes * 8 - bits; - uint16_t total_lz = 0; - uint16_t limb_lz; - (void)is_signed; +static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool fixup = false; -#if zig_little_endian - byte_offset = remaining_bytes; + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + if (is_signed && zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits); +} + +static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3)); + uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_prev_byte; + uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3)); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + lhs_byte_offset = size - lhs_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - while (remaining_bytes >= 128 / CHAR_BIT) { + { +#if zig_big_endian + lhs_byte_offset -= UINT16_C(1); +#endif + + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; + #if zig_little_endian - byte_offset -= 128 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); +#endif + } + + while (lhs_byte_offset != end_byte_offset) { +#if zig_big_endian + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - zig_u128 val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_prev_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 128 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 128 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 128 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 64 / CHAR_BIT) { -#if zig_little_endian - byte_offset -= 64 / CHAR_BIT; + { + uint8_t lhs_sign_fill = UINT8_C(0); + +#if zig_big_endian + res_byte_offset -= UINT16_C(1); #endif - { - uint64_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift); } - total_lz += limb_lz; - if (limb_lz < 64 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 64 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 64 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], lhs_sign_fill, res_byte_offset); #endif } +} + +static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t lhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3)); + uint8_t lhs_prev_byte = lhs_sign_fill; + uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3)); + bool overflow = false; - while (remaining_bytes >= 32 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 32 / CHAR_BIT; + lhs_byte_offset = size - lhs_byte_offset; +#else + res_byte_offset = size - res_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint32_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); - } + while (lhs_byte_offset != end_byte_offset) { +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#endif - total_lz += limb_lz; - if (limb_lz < 32 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 32 / CHAR_BIT; + overflow |= lhs_prev_byte != lhs_sign_fill; + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; #if zig_big_endian - byte_offset += 32 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 16 / CHAR_BIT; + end_byte_offset = UINT16_C(0); +#else + end_byte_offset = size; +#endif + + { + bool lhs_more_bytes = lhs_byte_offset != end_byte_offset; + +#if zig_little_endian + if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t lhs_byte = UINT8_C(0); + + if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset]; + + if (is_signed) { + int16_t shifted = zig_shr_i16(zig_or_i16( + zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_i16_intCast_u8(lhs_byte) + ), byte_shift); + int8_t truncated = zig_i8_truncate_i16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + + overflow |= zig_i16_intCast_i8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif + res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + } else { + uint16_t shifted = zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift); + uint8_t truncated = zig_u8_truncate_u16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + + overflow |= zig_u16_intCast_u8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + res_bytes[res_byte_offset] = truncated; + } - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 16 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_big_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + while (lhs_byte_offset != end_byte_offset) { #if zig_little_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - uint8_t val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 8 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_big_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - return total_lz; -} + { +#if zig_little_endian + res_byte_offset -= UINT16_C(1); +#endif -static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t total_tz = 0; - uint16_t limb_tz; - (void)is_signed; + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + byte_shift + )); #if zig_big_endian - byte_offset = remaining_bytes; + res_byte_offset += UINT16_C(1); #endif + } - while (remaining_bytes >= 128 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 128 / CHAR_BIT; +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#else + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); #endif - { - zig_u128 val_limb; + return overflow; +} - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u128(val_limb, 128); - } +static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits +} - total_tz += limb_tz; - if (limb_tz < 128) return total_tz; - remaining_bytes -= 128 / CHAR_BIT; +static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + (void)zig_shlo_big(res, lhs, rhs, is_signed, bits); +} -#if zig_little_endian - byte_offset += 128 / CHAR_BIT; -#endif +#define zig_big_shls_builtin(w) \ + static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + uint##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \ + } \ +\ + static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + int##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ + lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \ + } \ +\ + static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \ + const uint8_t *lhs_bytes = lhs; \ + if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \ + switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \ + case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \ + case INT32_C(0): return zig_minInt_big(res, false, bits); \ + case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \ + default: zig_unreachable(); \ + } \ } +zig_big_shls_builtin(8) +zig_big_shls_builtin(16) +zig_big_shls_builtin(32) +zig_big_shls_builtin(64) + +static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = bits / CHAR_BIT; + uint16_t end_byte_offset = UINT16_C(1); + uint16_t size = zig_int_bytes(bits); - while (remaining_bytes >= 64 / CHAR_BIT) { #if zig_big_endian - byte_offset -= 64 / CHAR_BIT; + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint64_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u64(val_limb, 64); - } + while (arg_byte_offset != end_byte_offset) { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); +#endif - total_tz += limb_tz; - if (limb_tz < 64) return total_tz; - remaining_bytes -= 64 / CHAR_BIT; + res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset]; #if zig_little_endian - byte_offset += 64 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 32 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 32 / CHAR_BIT; + { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); #endif { - uint32_t val_limb; + uint8_t byte = arg_bytes[arg_byte_offset]; + uint8_t fill = is_signed + ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) + : UINT8_C(0); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u32(val_limb, 32); + res_bytes[res_byte_offset] = byte; + +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif } + } +} - total_tz += limb_tz; - if (limb_tz < 32) return total_tz; - remaining_bytes -= 32 / CHAR_BIT; +static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t end_byte_offset = UINT16_C(0); + uint8_t arg_prev_byte; + uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + { #if zig_little_endian - byte_offset += 32 / CHAR_BIT; + arg_byte_offset -= UINT16_C(1); +#endif + + arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); + +#if zig_big_endian + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { + while (arg_byte_offset != end_byte_offset) { #if zig_big_endian - byte_offset -= 16 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); +#else + arg_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u16(val_limb, 16); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), + zig_u16_intCast_u8(arg_prev_byte) + ), byte_shift)); + arg_prev_byte = arg_byte; } - total_tz += limb_tz; - if (limb_tz < 16) return total_tz; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_little_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + { + uint8_t arg_sign_fill = UINT8_C(0); + #if zig_big_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); #endif - { - uint8_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u8(val_limb, 8); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift); } - total_tz += limb_tz; - if (limb_tz < 8) return total_tz; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_little_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], arg_sign_fill, res_byte_offset); #endif } - - return total_tz; } -static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; +static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); uint16_t total_pc = 0; (void)is_signed; #if zig_big_endian - byte_offset = remaining_bytes; + byte_offset = zig_int_bytes(bits); #endif while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 128 / CHAR_BIT; #endif { - zig_u128 val_limb; + zig_u128 arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u128(val_limb, 128); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 128 / CHAR_BIT; @@ -3575,15 +5302,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 64 / CHAR_BIT; #endif { - uint64_t val_limb; + uint64_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u64(val_limb, 64); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 64 / CHAR_BIT; @@ -3594,15 +5323,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 32 / CHAR_BIT; #endif { - uint32_t val_limb; + uint32_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u32(val_limb, 32); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 32 / CHAR_BIT; @@ -3613,15 +5344,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 16 / CHAR_BIT; #endif { - uint16_t val_limb; + uint16_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u16(val_limb, 16); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 16 / CHAR_BIT; @@ -3632,15 +5365,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 8 / CHAR_BIT; #endif { - uint8_t val_limb; + uint8_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u8(val_limb, 8); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 8 / CHAR_BIT; @@ -3653,6 +5388,274 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ return total_pc; } +static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = UINT16_C(0); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + uint16_t total_tz = UINT16_C(0); + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits); +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t remaining_bytes = byte_offset; + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool sign_limb = true; + uint16_t total_lz = UINT16_C(0); + uint16_t limb_lz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits) - remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + /* ========================= Floating Point Support ========================= */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ @@ -3687,29 +5690,29 @@ long double __cdecl nanl(char const* input); #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) #else -#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) -#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) -#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) -#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) -#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) +#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) +#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) +#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) +#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) +#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) #endif #define zig_has_f16 1 #define zig_libc_name_f16(name) __##name##h #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) -#if FLT_MANT_DIG == 11 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f -#elif DBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 typedef double zig_f16; #define zig_make_f16(fp, repr) fp -#elif LDBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 -#elif defined(__SIZEOF_FP16__) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__) typedef __fp16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #else @@ -3723,11 +5726,6 @@ typedef uint16_t zig_f16; #undef zig_init_special_f16 #define zig_init_special_f16(sign, name, arg, repr) repr #endif -#if defined(zig_darwin) && defined(zig_x86) -typedef uint16_t zig_compiler_rt_f16; -#else -typedef zig_f16 zig_compiler_rt_f16; -#endif #define zig_has_f32 1 #define zig_libc_name_f32(name) name##f @@ -3736,16 +5734,16 @@ typedef zig_f16 zig_compiler_rt_f16; #else #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 24 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 typedef float zig_f32; #define zig_make_f32(fp, repr) fp##f -#elif DBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 typedef double zig_f32; #define zig_make_f32(fp, repr) fp -#elif LDBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l -#elif FLT32_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 typedef _Float32 zig_f32; #define zig_make_f32(fp, repr) fp##f32 #else @@ -3768,19 +5766,19 @@ typedef uint32_t zig_f32; #else #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 53 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_make_f64(fp, repr) fp##f -#elif DBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 typedef double zig_f64; #define zig_make_f64(fp, repr) fp -#elif LDBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l -#elif FLT64_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 typedef _Float64 zig_f64; #define zig_make_f64(fp, repr) fp##f64 -#elif FLT32X_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 typedef _Float32x zig_f64; #define zig_make_f64(fp, repr) fp##f32x #else @@ -3798,7 +5796,14 @@ typedef uint64_t zig_f64; #define zig_has_f80 1 #define zig_libc_name_f80(name) __##name##x #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) -#if FLT_MANT_DIG == 64 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI +#undef zig_has_f80 +typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80; +#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent } +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#define zig_mantissa_repr_f80(arg) (arg).mantissa +#define zig_exponent_repr_f80(arg) (arg).exponent +#elif FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f #elif DBL_MANT_DIG == 64 @@ -3818,10 +5823,18 @@ typedef __float80 zig_f80; #define zig_make_f80(fp, repr) fp##l #else #undef zig_has_f80 -#define zig_has_f80 0 -#define zig_repr_f80 u128 typedef zig_u128 zig_f80; +#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa) +#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa) +#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg) +#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg) +#endif +#ifndef zig_has_f80 +#define zig_has_f80 0 #define zig_make_f80(fp, repr) repr +#ifndef zig_make_repr_f80 +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#endif #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr #undef zig_init_special_f80 @@ -3833,11 +5846,20 @@ typedef zig_u128 zig_f80; #else #define zig_f128_has_miscompilations 0 #endif - #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI +#undef zig_has_f128 +#if zig_little_endian +typedef struct { uint64_t lo, hi; } zig_f128; +#else +typedef struct { uint64_t hi, lo; } zig_f128; +#endif +#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_lo_repr_f128(arg) (arg).lo +#define zig_hi_repr_f128(arg) (arg).hi +#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 @@ -3859,27 +5881,38 @@ typedef __float128 zig_f128; #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) #else #undef zig_has_f128 -#define zig_has_f128 0 -#undef zig_make_special_f128 -#undef zig_init_special_f128 -#if defined(zig_darwin) || defined(zig_aarch64) -typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; -zig_basic_operator(zig_v2u64, xor_v2u64, ^) -#define zig_repr_f128 v2u64 -typedef zig_v2u64 zig_f128; -#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } -#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 -#define zig_make_f128(fp, repr) zig_make_f128_##repr -#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr -#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr +#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) +#if defined(zig_msvc) && !defined(__clang__) +#include +typedef __m128i zig_f128; +#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } +#define zig_lo_repr_f128(arg) (arg).m128i_u64[0] +#define zig_hi_repr_f128(arg) (arg).m128i_u64[1] +#else +typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; +#define zig_init_repr_f128(hi, lo) { lo, hi } +#define zig_lo_repr_f128(arg) (arg)[0] +#define zig_hi_repr_f128(arg) (arg)[1] +#endif #else -#define zig_repr_f128 u128 typedef zig_u128 zig_f128; +#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo) +#define zig_lo_repr_f128(arg) zig_lo_u128(arg) +#define zig_hi_repr_f128(arg) zig_hi_u128(arg) +#endif +#endif +#ifndef zig_has_f128 +#define zig_has_f128 0 #define zig_make_f128(fp, repr) repr +#ifndef zig_make_repr_f128 +#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo) +#endif +#undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 #define zig_init_special_f128(sign, name, arg, repr) repr #endif -#endif #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) /* Emulate msvc abi on a gnu compiler */ @@ -3892,84 +5925,141 @@ typedef zig_f128 zig_c_longdouble; typedef long double zig_c_longdouble; #endif -#define zig_bitCast_float(Type, ReprType) \ - static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ - zig_##Type result; \ - memcpy(&result, &repr, sizeof(result)); \ - return result; \ +#if __AVR__ +typedef signed char zig_FloatCompareResult; +#elif defined(zig_aarch64) +typedef signed int zig_FloatCompareResult; +#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ +typedef signed long zig_FloatCompareResult; +#else +typedef signed long long zig_FloatCompareResult; +#endif + +#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \ + static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \ + UnsignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_u##iw##_truncate_u##iw(res, w); \ + } \ + static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \ + SignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_i##iw##_truncate_i##iw(res, w); \ + } +zig_bitCast_float(16, 16, uint16_t, int16_t) +zig_bitCast_float(32, 32, uint32_t, int32_t) +zig_bitCast_float(64, 64, uint64_t, int64_t) +#if zig_has_f80 +zig_bitCast_float(80, 128, zig_u128, zig_i128) +#else +static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg)); +} +static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) { + return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) { + return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +#endif +static inline zig_f80 zig_f80_bitCast_big(const void *arg) { + return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80))); +} +static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) { + if (res_is_signed) { + zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits); + } else { + zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits); } -zig_bitCast_float(f16, uint16_t) -zig_bitCast_float(f32, uint32_t) -zig_bitCast_float(f64, uint64_t) -zig_bitCast_float(f80, zig_u128) -zig_bitCast_float(f128, zig_u128) +} +#if zig_has_f128 +zig_bitCast_float(128, 128, zig_u128, zig_i128) +#else +static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg)); +} +static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) { + return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) { + return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +#endif -#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ - zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ +#define zig_convert_float_00(ResType, operation, ArgType, version) \ + zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ + return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) +#define zig_convert_float_01(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_10(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_11(ResType, operation, ArgType, version) \ + return (ResType)arg +#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ - ResType res; \ - ExternResType extern_res; \ - ExternArgType extern_arg; \ - memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ - extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ - memcpy(&res, &extern_res, sizeof(res)); \ - return extern_res; \ + zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ + zig_has_##arg_when)(ResType, operation, ArgType, version); \ } -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) -#ifdef __ARM_EABI__ +#define zig_convert_floats(SmallType, BigType) \ + zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ + zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) +zig_convert_floats(f16, f32) +zig_convert_floats(f16, f64) +zig_convert_floats(f16, f80) +zig_convert_floats(f16, f128) +zig_convert_floats(f32, f64) +zig_convert_floats(f32, f80) +zig_convert_floats(f32, f128) +zig_convert_floats(f64, f80) +zig_convert_floats(f64, f128) +zig_convert_floats(f80, f128) -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); -static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); -static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } - -#else /* __ARM_EABI__ */ - -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) - -#endif /* __ARM_EABI__ */ - -#define zig_float_negate_builtin_0(w, c, sb) \ - zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) -#define zig_float_negate_builtin_1(w, c, sb) -arg -#define zig_float_negate_builtin(w, c, sb) \ +#define zig_float_negate_builtin_0(w, sb) \ + zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) +#define zig_float_negate_builtin_1(w, sb) -arg +#define zig_float_negate_builtin(w, sb) \ static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \ - return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \ + return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \ } -zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) -zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) -zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) -zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) -zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) +zig_float_negate_builtin(16, UINT16_C(1) << 15) +zig_float_negate_builtin(32, UINT32_C(1) << 31) +zig_float_negate_builtin(64, UINT64_C(1) << 63) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) +zig_float_negate_builtin(80, UINT16_C(1) << 15) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg)) +zig_float_negate_builtin(128, UINT64_C(1) << 63) #define zig_float_less_builtin_0(Type, operation) \ - zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \ + zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \ zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ + return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ } #define zig_float_less_builtin_1(Type, operation) \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -3994,13 +6084,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) return lhs operator rhs; \ } +#define zig_float_builtins(w) \ + zig_common_float_builtins(w) \ + zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \ + zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, ) #define zig_common_float_builtins(w) \ - zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ + zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \ @@ -4031,82 +6160,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \ zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \ \ - static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ - return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \ + return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \ } -zig_common_float_builtins(16) -zig_common_float_builtins(32) -zig_common_float_builtins(64) -zig_common_float_builtins(80) -zig_common_float_builtins(128) - -#define zig_float_builtins(w) \ - zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) zig_float_builtins(16) -zig_float_builtins(80) -zig_float_builtins(128) - -#ifdef __ARM_EABI__ - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); -static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); -static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); -static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); -static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); -static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); -static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); -static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); -static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); -static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); -static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); -static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); -static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } - -#else /* __ARM_EABI__ */ - zig_float_builtins(32) zig_float_builtins(64) - -#endif /* __ARM_EABI__ */ +zig_float_builtins(80) +#if defined(zig_x86_32) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_f128 arg); + return __floattitf(zig_f128_bitCast_i128(arg)); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(zig_f128 arg); + return __floatuntitf(zig_f128_bitCast_u128(arg)); +} +#elif defined(zig_x86_64) && defined(zig_windows) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_i128 arg); + return __floattitf(arg); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi); + return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg)); +} +#else +zig_float_builtins(128) +#endif /* ============================ Atomics Support ============================= */ @@ -4410,19 +6505,19 @@ typedef int zig_memory_order; } \ static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ - } \ + } \ static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } zig_msvc_atomics( u8, uint8_t, char, 8, 8) @@ -4465,14 +6560,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } \ static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } @@ -4502,9 +6597,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) { - void* val = (void*)__iso_volatile_load32(obj); + void* value = (void*)__iso_volatile_load32(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { @@ -4532,9 +6627,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) { - void* val = (void*)__iso_volatile_load64(obj); + void* value = (void*)__iso_volatile_load64(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 9ecd3a4e0b1f4483c878e056cf3786bccafed62b..d1605b457e2f3673807c16fd10836612aae804d5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -164,7 +164,8 @@ const BlockData = struct { const LocalType = struct { type: Type, - alignment: Alignment, + alignment: Alignment = .none, + array_len: u2 = 1, }; const LocalIndex = u16; @@ -184,13 +185,11 @@ const ValueRenderLocation = enum { } }; -const BuiltinInfo = enum { none, bits }; +const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits }; const reserved_idents = std.StaticStringMap(void).initComptime(.{ // C language - .{ "alignas", { - @setEvalBranchQuota(4000); - } }, + .{ "alignas", {} }, .{ "alignof", {} }, .{ "asm", {} }, .{ "atomic_bool", {} }, @@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ // stddef.h .{ "offsetof", {} }, + // math.h (only symbols exported by compiler-rt) + .{ "ceil", {} }, + .{ "ceilf", {} }, + .{ "ceilf128", {} }, + .{ "ceill", {} }, + .{ "cos", {} }, + .{ "cosf", {} }, + .{ "cosf128", {} }, + .{ "cosl", {} }, + .{ "exp", {} }, + .{ "exp2", {} }, + .{ "exp2f", {} }, + .{ "exp2f128", {} }, + .{ "exp2l", {} }, + .{ "expf", {} }, + .{ "expf128", {} }, + .{ "expl", {} }, + .{ "fabs", {} }, + .{ "fabsf", {} }, + .{ "fabsf128", {} }, + .{ "fabsl", {} }, + .{ "floor", {} }, + .{ "floorf", {} }, + .{ "floorf128", {} }, + .{ "floorl", {} }, + .{ "fma", {} }, + .{ "fmaf", {} }, + .{ "fmaf128", {} }, + .{ "fmal", {} }, + .{ "fmax", {} }, + .{ "fmaxf", {} }, + .{ "fmaxf128", {} }, + .{ "fmaxl", {} }, + .{ "fmin", {} }, + .{ "fminf", {} }, + .{ "fminf128", {} }, + .{ "fminl", {} }, + .{ "fmod", {} }, + .{ "fmodf", {} }, + .{ "fmodf128", {} }, + .{ "fmodl", {} }, + .{ "log", {} }, + .{ "log10", {} }, + .{ "log10f", {} }, + .{ "log10f128", {} }, + .{ "log10l", {} }, + .{ "log2", {} }, + .{ "log2f", {} }, + .{ "log2f128", {} }, + .{ "log2l", {} }, + .{ "logf", {} }, + .{ "logf128", {} }, + .{ "logl", {} }, + .{ "round", {} }, + .{ "roundf", {} }, + .{ "roundf128", {} }, + .{ "roundl", {} }, + .{ "sin", {} }, + .{ "sincos", {} }, + .{ "sincosf", {} }, + .{ "sincosf128", {} }, + .{ "sincosl", {} }, + .{ "sinf", {} }, + .{ "sinf128", {} }, + .{ "sinl", {} }, + .{ "sqrt", {} }, + .{ "sqrtf", {} }, + .{ "sqrtf128", {} }, + .{ "sqrtl", {} }, + .{ "tan", {} }, + .{ "tanf", {} }, + .{ "tanf128", {} }, + .{ "tanl", {} }, + .{ "trunc", {} }, + .{ "truncf", {} }, + .{ "truncf128", {} }, + .{ "truncl", {} }, + // windows.h + .{"DUMMYSTRUCTNAME"}, + .{"DUMMYSTRUCTNAME2"}, + .{"DUMMYSTRUCTNAME3"}, + .{"DUMMYSTRUCTNAME4"}, + .{"DUMMYSTRUCTNAME5"}, + .{"DUMMYSTRUCTNAME6"}, + .{"DUMMYUNIONNAME"}, + .{"DUMMYUNIONNAME2"}, + .{"DUMMYUNIONNAME3"}, + .{"DUMMYUNIONNAME4"}, + .{"DUMMYUNIONNAME5"}, + .{"DUMMYUNIONNAME6"}, + .{"DUMMYUNIONNAME7"}, + .{"DUMMYUNIONNAME8"}, + .{"DUMMYUNIONNAME9"}, .{ "max", {} }, .{ "min", {} }, }); @@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool { } } - // windows.h - if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or - mem.startsWith(u8, ident, "DUMMYUNIONNAME")) - { - return true; - } - // CType if (mem.startsWith(u8, ident, "enum__") or mem.startsWith(u8, ident, "bitpack__") or @@ -469,10 +554,7 @@ pub const Function = struct { } fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { - return f.allocAlignedLocal(inst, .{ - .type = ty, - .alignment = .none, - }); + return f.allocAlignedLocal(inst, .{ .type = ty }); } /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should @@ -564,10 +646,6 @@ pub const Function = struct { return f.dg.renderType(w, ty); } - fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { - return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); - } - fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { return f.dg.fmtIntLiteralDec(val, .other); } @@ -672,7 +750,9 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const ptr_ty: Type = .fromInterned(uav.orig_ty); if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } switch (ip.indexToKey(uav.val)) { @@ -737,8 +817,10 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type); const ptr_ty = try pt.navPtrType(owner_nav); - if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } // We shouldn't cast C function pointers as this is UB (when you call @@ -758,6 +840,26 @@ pub const DeclGen = struct { if (need_cast) try w.writeByte(')'); } + fn renderOpvPointer( + dg: *DeclGen, + w: *Writer, + ptr_ty: Type, + location: ValueRenderLocation, + ) Error!void { + const zcu = dg.pt.zcu; + const target = zcu.getTarget(); + try w.writeByte('('); + try dg.renderType(w, ptr_ty); + return w.print("){f}", .{fmtUnsignedIntLiteralSmall( + target, + .uintptr_t, + ptr_ty.ptrAlignment(zcu).forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())), + location == .static_initializer, + 16, + .lower, + )}); + } + fn renderPointer( dg: *DeclGen, w: *Writer, @@ -959,9 +1061,6 @@ pub const DeclGen = struct { const bits = ty.floatBits(target); const f128_val = val.toFloat(f128, zcu); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = pt.intType(.unsigned, bits) catch unreachable; - assert(bits <= 128); var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; var repr_val_big = BigInt.Mutable{ @@ -971,29 +1070,27 @@ pub const DeclGen = struct { }; switch (bits) { + else => unreachable, 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), - else => unreachable, } - var empty = true; if (std.math.isFinite(f128_val)) { try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { + else => unreachable, 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}), 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}), 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}), 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}), 128 => try w.print("{x}", .{f128_val}), - else => unreachable, } try w.writeAll(", "); - empty = false; } else { // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan const operation = if (std.math.isNan(f128_val)) @@ -1028,6 +1125,7 @@ pub const DeclGen = struct { try w.writeAll(operation); try w.writeAll(", "); if (std.math.isNan(f128_val)) switch (bits) { + else => unreachable, // We only actually need to pass the significand, but it will get // properly masked anyway, so just pass the whole value. 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), @@ -1035,16 +1133,23 @@ pub const DeclGen = struct { 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), - else => unreachable, }; try w.writeAll(", "); - empty = false; } - try w.print("{f}", .{try dg.fmtIntLiteralHex( - try pt.intValue_big(repr_ty, repr_val_big.toConst()), - location, - )}); - if (!empty) try w.writeByte(')'); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = pt.intType(.unsigned, bits) catch unreachable; + try w.print("{f}", .{try dg.fmtIntLiteralHex( + try pt.intValue_big(repr_ty, repr_val_big.toConst()), + location, + )}); + }, + 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer), + 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer), + } + try w.writeByte(')'); }, .slice => |slice| { if (!location.isInitializer()) { @@ -1319,22 +1424,29 @@ pub const DeclGen = struct { .f128_type, => { const bits = ty.floatBits(target); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { - 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), - 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), - 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), - 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), - 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), else => unreachable, + 16 => try w.print("{x}", .{undefPattern(f16)}), + 32 => try w.print("{x}", .{undefPattern(f32)}), + 64 => try w.print("{x}", .{undefPattern(f64)}), + 80 => try w.print("{x}", .{undefPattern(f80)}), + 128 => try w.print("{x}", .{undefPattern(f128)}), } try w.writeAll(", "); - try dg.renderUndefValue(w, repr_ty, .other); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; + try dg.renderUndefValue(w, repr_ty, .other); + }, + 80 => try undefPattern(F80Repr).write(w, target, location == .static_initializer), + 128 => try undefPattern(F128Repr).write(w, target, location == .static_initializer), + } return w.writeByte(')'); }, .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), @@ -1726,136 +1838,6 @@ pub const DeclGen = struct { try w.print("{f}", .{cty.fmtTypeName(zcu)}); } - const IntCastContext = union(enum) { - c_value: struct { - f: *Function, - value: CValue, - v: Vectorize, - }, - value: struct { - value: Value, - }, - - pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void { - switch (self.*) { - .c_value => |v| { - try v.f.writeCValue(w, v.value, location); - try v.v.elem(v.f, w); - }, - .value => |v| try dg.renderValue(w, v.value, location), - } - } - }; - fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(pt.zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(pt.zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(pt.zcu)) src_eff_ty.intInfo(pt.zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - return !needs_cast and !src_is_ptr; - } else return false; - } - /// Renders a cast to an int type, from either an int or a pointer. - /// - /// Some platforms don't have 128 bit integers, so we need to use - /// the zig_make_ and zig_lo_ macros in those cases. - /// - /// | Dest type bits | Src type | Result - /// |------------------|------------------|---------------------------| - /// | < 64 bit integer | pointer | (zig_)(zig_size)src - /// | < 64 bit integer | < 64 bit integer | (zig_)src - /// | < 64 bit integer | > 64 bit integer | zig_lo(src) - /// | > 64 bit integer | pointer | zig_make_(0, (zig_size)src) - /// | > 64 bit integer | < 64 bit integer | zig_make_(0, src) - /// | > 64 bit integer | > 64 bit integer | zig_make_(zig_hi_(src), zig_lo_(src)) - fn renderIntCast( - dg: *DeclGen, - w: *Writer, - dest_ty: Type, - context: IntCastContext, - src_ty: Type, - location: ValueRenderLocation, - ) !void { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - - if (needs_cast) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, location); - } else if (dest_bits <= 64 and src_bits > 64) { - assert(!src_is_ptr); - if (dest_bits < 64) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - try w.writeAll("zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else if (dest_bits > 64 and src_bits <= 64) { - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(0, "); - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else { - assert(!src_is_ptr); - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(zig_hi_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("), zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("))"); - } - } - /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. fn renderTypeAndName( dg: *DeclGen, @@ -2000,6 +1982,7 @@ pub const DeclGen = struct { switch (info) { .none => if (!is_big) return, .bits => {}, + .bits_none, .big_temp_bits => unreachable, } const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{ @@ -2056,6 +2039,72 @@ const CQualifiers = packed struct { restrict: bool = false, }; +pub fn genHeader(zcu: *Zcu, w: *Writer) !void { + const gpa = zcu.comp.gpa; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var ctype_deps: CType.Dependencies = .empty; + defer ctype_deps.deinit(gpa); + + const target = zcu.getTarget(); + switch (target.abi) { + .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), + else => {}, + } + for ([_]u16{ 16, 32, 64, 80, 128 }) |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => {}, + .soft => try w.print("#define ZIG_TARGET_SOFT_COMPILER_RT_F{d}_ABI\n", .{bits}), + }; + try w.print( + \\#define ZIG_TARGET_MAX_INT_ALIGNMENT {d} + \\#include "zig.h" + \\ + \\ + , + .{target.cMaxIntAlignment()}, + ); + + var basic_ty: Type = .fromInterned(.first_type); + while (true) : ({ + basic_ty = .fromInterned(@fromBackingInt(@intCast(@backingInt(basic_ty.toIntern()) + 1))); + if (basic_ty.toIntern() == InternPool.Index.last_type) break; + }) { + switch (basic_ty.toIntern()) { + else => {}, + .anyframe_type, + .adhoc_inferred_error_set_type, + .generic_poison_type, + => continue, // skip unsupported types + } + const basic_cty: CType = try .lower(basic_ty, &ctype_deps, arena.allocator(), zcu); + switch (basic_cty) { + .void => {}, // no layout to check + .bool, + .int, + .float, + => try CType.render_defs.writeStaticAssertTypeLayout(basic_ty, basic_cty, w, zcu), + .@"fn", + .@"enum", + .bitpack, + .@"struct", + .union_auto, + .union_extern, + .slice, + .opt, + .arr, + .vec, + .errunion, + .aligned, + .bigint, + .pointer, + .array, + .function, + => {}, + } + } +} + pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { for (zcu.global_assembly.values()) |asm_source| { try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)}); @@ -2070,16 +2119,16 @@ pub fn genErrDecls( const ip = &zcu.intern_pool; const names = ip.global_error_set.getNamesFromMainThread(); - // Don't generate an invalid empty enum if the global error set is empty! - if (names.len > 0) { - try w.writeAll("enum {\n"); - for (names, 1..) |name_nts, value| { - try w.writeByte(' '); - try renderErrorName(w, name_nts.toSlice(ip)); - try w.print(" = {d}u,\n", .{value}); - } - try w.writeAll("};\n"); + // Don't generate an invalid empty enum/array if the global error set is empty! + if (names.len == 0) return; + + try w.writeAll("enum {\n"); + for (names, 1..) |name_nts, value| { + try w.writeByte(' '); + try renderErrorName(w, name_nts.toSlice(ip)); + try w.print(" = {d}u,\n", .{value}); } + try w.writeAll("};\n"); for (names) |name_nts| { const name = name_nts.toSlice(ip); @@ -2093,7 +2142,7 @@ pub fn genErrDecls( "static {s} const zig_errorName[{d}] = {{", .{ slice_const_u8_sentinel_0_type_name, names.len }, ); - if (names.len > 0) try w.writeByte('\n'); + try w.writeByte('\n'); for (names) |name_nts| { const name = name_nts.toSlice(ip); try w.print( @@ -2114,10 +2163,18 @@ pub fn genTagNameFn( const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); assert(loaded_enum.field_names.len > 0); - if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { - @panic("TODO CBE: tagName for enum over 64 bits"); + switch (CType.classifyInt(enum_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => {}, + .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"), + }, + .big => @panic("TODO CBE: tagName for bigint enums"), } + if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ + loaded_enum.name.fmt(ip), + }); try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ slice_const_u8_sentinel_0_type_name, fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), @@ -2291,6 +2348,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E .{ .nav = nav_index }, ); try header_writer.writeAll(" {\n "); + if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)}); f.free_locals_map.clearRetainingCapacity(); @@ -2346,6 +2404,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E for (list.keys()) |local_index| { const local = f.locals.items[local_index]; try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment); + if (local.array_len != 1) try header_writer.print("[{d}]", .{local.array_len}); try header_writer.writeAll(";\n "); } } @@ -2461,7 +2520,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); try w.writeAll(" = "); try dg.renderValue(w, options.init_val, .static_initializer); - try w.writeAll(";\n"); + try w.writeByte(';'); + if (dg.owner_nav.unwrap()) |nav_index| { + const ip = &zcu.intern_pool; + if (!dg.mod.strip) try w.print(" /* {f} */", .{ip.getNav(nav_index).fqn.fmt(ip)}); + } + try w.writeByte('\n'); } pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { name: CValue, @@ -2662,22 +2726,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .mul => try airBinOp(f, inst, "*", "mul", .none), .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none), - .div_float => try airBinBuiltinCall(f, inst, "div", .none), + .div_float => try airBinBuiltinCall(f, inst, "div", .big_temp_bits), - .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), + .div_trunc, .div_exact => try airBinOp(f, inst, "/", "divTrunc", .big_temp_bits), .rem => blk: { const bin_op = air_datas[@intFromEnum(inst)].bin_op; const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_scalar_ty.isInt(zcu)) - try airBinOp(f, inst, "%", "rem", .none) + try airBinOp(f, inst, "%", "rem", .big_temp_bits) else try airBinBuiltinCall(f, inst, "fmod", .none); }, - .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), - .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none), - .mod => try airBinBuiltinCall(f, inst, "mod", .none), + .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits), + .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits), + .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits), .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none), .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), @@ -2687,7 +2751,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits), - .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits), + .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits_none), .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none), .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none), @@ -2764,8 +2828,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .int_from_error => try airNopCast(f, inst), .union_from_enum => try airUnionFromEnum(f, inst), .bit_cast => try airBitCast(f, inst), - .int_cast => try airIntCast(f, inst), - .trunc => try airTrunc(f, inst), + .int_cast => try airIntCast(f, inst, "intCast", .none), + .trunc => try airIntCast(f, inst, "truncate", .bits), .load => try airLoad(f, inst), .store => try airStore(f, inst, false), .store_safe => try airStore(f, inst, true), @@ -2783,9 +2847,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .get_union_tag => try airGetUnionTag(f, inst), .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits), .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits), - .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits), - .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits), - .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits), + .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits), + .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits), + .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits), .tag_name => try airTagName(f, inst), .error_name => try airErrorName(f, inst), .splat => try airSplat(f, inst), @@ -3124,7 +3188,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); - if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; + if (!elem_ty.hasRuntimeBits(zcu)) { + const w = &f.code.writer; + const local = try f.allocLocal(inst, inst_ty); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + try f.dg.renderOpvPointer(w, inst_ty, .other); + try w.writeByte(';'); + try f.newline(); + return local; + } const local = try f.allocLocalValue(.{ .type = elem_ty, @@ -3298,120 +3371,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { } } -fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { +fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); + const inst_ty = ty_op.ty.toType(); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - - // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. - if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { - return f.moveCValue(inst, inst_ty, operand); - } - - const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); - try w.writeByte(';'); - try f.newline(); - try v.end(f, inst, w); - return local; -} - -fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.dg.pt; - const zcu = pt.zcu; - const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const operand_scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(zcu); - const dest_int_info = inst_scalar_ty.intInfo(zcu); - const dest_bits = dest_int_info.bits; - const dest_c_bits = toCIntBits(dest_bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - const scalar_int_info = scalar_ty.intInfo(zcu); + if (!is_big) try reap(f, inst, &.{ty_op.operand}); - const need_cast = dest_c_bits < 64; - const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64; - const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); - if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{ty_op.operand}); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - if (need_cast) { - try w.writeByte('('); - try f.renderType(w, inst_scalar_ty); - try w.writeByte(')'); - } - if (need_lo) { - try w.writeAll("zig_lo_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); + if (!ref_ret) { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); } - if (!need_mask) { - try f.writeCValue(w, operand, .other); + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_{s}_", .{operation}); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); - } else switch (dest_int_info.signedness) { - .unsigned => { - try w.writeAll("zig_and_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - try w.print(", {f})", .{ - try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), - }); - }, - .signed => { - const c_bits = toCIntBits(scalar_int_info.bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const shift_val = try pt.intValue(.u8, c_bits - dest_bits); - - try w.writeAll("zig_shr_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - if (c_bits == 128) { - try w.print("(zig_bitCast_i{d}(", .{c_bits}); - } else { - try w.print("((int{d}_t)", .{c_bits}); - } - try w.print("zig_shl_u{d}(", .{c_bits}); - if (c_bits == 128) { - try w.print("zig_bitCast_u{d}(", .{c_bits}); - } else { - try w.print("(uint{d}_t)", .{c_bits}); - } - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - }, + try w.writeAll(", "); } - if (need_lo) try w.writeByte(')'); - try w.writeByte(';'); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info); + try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none); + try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); + return local; } @@ -3525,39 +3535,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); + const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const inst_ty = f.typeOfIndex(inst); - const operand_ty = f.typeOf(bin_op.lhs); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); + const local = try f.allocLocal(inst, f.typeOfIndex(inst)); + if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + const v = try Vectorize.start(f, inst, w, lhs_ty); try f.writeCValueMember(w, local, .{ .field = 1 }); try v.elem(f, w); - try w.writeAll(" = zig_"); + try w.writeAll(" = "); + try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll("o_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); try w.writeByte('('); // '&dest', possibly preceded by a cast - switch (zcu.intern_pool.indexToKey(scalar_ty.toIntern())) { + switch (zcu.intern_pool.indexToKey(lhs_scalar_ty.toIntern())) { .int_type => {}, // we already have a '[u]intX_t *' .simple_type => { // '&dest' will be something like a 'uintptr_t *', which might be a different C type to // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a // cast on the *operands* because they are passed by value (except for big integers, // where this issue doesn't exist because no "simple" int type needs bigint repr). - try w.print("({s}int{d}_t *)", .{ - if (scalar_ty.isUnsignedInt(zcu)) "u" else "", - scalar_ty.abiSize(zcu) * 8, - }); + const inst_int_info = lhs_scalar_ty.intInfo(zcu); + try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) { + .signed => "", + .unsigned => "u", + }, inst_int_info.bits }); }, else => unreachable, } @@ -3566,14 +3583,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info); try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); @@ -3622,8 +3649,18 @@ fn airBinOp( const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); const scalar_ty = operand_ty.scalarType(zcu); - if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, info); + + builtin: { + if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, info); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3662,19 +3699,21 @@ fn airCmpOp( const lhs_ty = f.typeOf(data.lhs); const scalar_ty = lhs_ty.scalarType(zcu); - if (scalar_ty.isInt(zcu)) { - const scalar_bits = scalar_ty.bitSize(zcu); - if (scalar_bits > 64) return airCmpBuiltinCall( - f, - inst, - data, - operator, - .cmp, - if (scalar_bits > 128) .bits else .none, - ); + builtin: { + if (scalar_ty.isInt(zcu)) { + switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none); + } + if (scalar_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); } - if (scalar_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); const inst_ty = f.typeOfIndex(inst); const lhs = try f.resolveInst(data.lhs); @@ -3716,21 +3755,23 @@ fn airEquality( const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - if (operand_ty.isAbiInt(zcu)) { - const operand_bits = operand_ty.bitSize(zcu); - if (operand_bits > 64) return airCmpBuiltinCall( - f, - inst, - bin_op, - operator, - .cmp, - if (operand_bits > 128) .bits else .none, - ); + + builtin: { + if (operand_ty.isAbiInt(zcu)) { + switch (CType.classifyInt(operand_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none); + } + if (operand_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); } - if (operand_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3809,7 +3850,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(w, local, .other); try w.writeAll(" = "); try f.writeCValue(w, operand, .other); - try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);"); + try w.writeAll(" <= sizeof(zig_errorName) / sizeof(*zig_errorName);"); try f.newline(); return local; } @@ -3862,8 +3903,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, .none); + builtin: { + if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, .none); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3979,10 +4029,7 @@ fn airCall( try w.writeAll("(void)"); break :result .none; } else { - const local = try f.allocAlignedLocal(inst, .{ - .type = ret_ty, - .alignment = .none, - }); + const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty }); try f.writeCValue(w, local, .other); try w.writeAll(" = "); break :result local; @@ -4058,16 +4105,7 @@ fn airCall( fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; const w = &f.code.writer; - // TODO re-evaluate whether to emit these or not. If we naively emit - // these directives, the output file will report bogus line numbers because - // every newline after the #line directive adds one to the line. - // We also don't print the filename yet, so the output is strictly unhelpful. - // If we wanted to go this route, we would need to go all the way and not output - // newlines until the next dbg_stmt occurs. - // Perhaps an additional compilation option is in order? - //try w.print("#line {d}", .{dbg_stmt.line + 1}); - //try f.newline(); - try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); + try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); try f.newline(); return .none; } @@ -4433,12 +4471,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_scalar_ty = dest_ty.scalarType(zcu); - // Some cases are handled with a simple cast: - // * float -> float - // * bool -> int if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu))) { + // Some cases are handled with a simple cast: + // * float -> float + // * bool -> int try f.writeCValue(w, dest_local, .other); try v.elem(f, w); try w.writeAll(" = ("); @@ -4458,85 +4496,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { try v.elem(f, w); try w.writeAll(" != 0;"); try f.newline(); - } else if (dest_scalar_ty.isRuntimeFloat()) { - // For int->float, just do a memcpy. - assert(operand_scalar_ty.isAbiInt(zcu)); - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), - } - try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); - try f.newline(); } else { - // The only remaining possibility is that the result is an integer. We will need to use - // `zig_wrap_*` to correct the "padding" bits after we populate the value bits. - assert(dest_scalar_ty.isAbiInt(zcu)); assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu)); + assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu)); - // memcpy the value... - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), + const ref_ret = lowersToBigInt(dest_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); + + if (!ref_ret) { + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); + try w.writeAll("_bitCast_"); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(", "); } + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); + try f.dg.renderBuiltinInfo( + w, + dest_scalar_ty, + if (operand_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isRuntimeFloat()) .none else .bits, + ); + try w.writeAll(");"); try f.newline(); - - // ...and ensure padding bits have the correct value. - switch (CType.classifyInt(dest_scalar_ty, zcu)) { - .void => unreachable, // opv - .small => { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(" = zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits); - try w.writeAll(");"); - try f.newline(); - }, - .big => |big| { - const dest_info = dest_scalar_ty.intInfo(zcu); - const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) { - .little => big.limbs_len - 1, - .big => 0, - }; - const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1; - if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{ - padding_index, - signAbbrev(dest_info.signedness), - big.limb_size.bits(), - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits }); - } else { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{ - padding_index, - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits }); - try f.newline(); - } - }, - } } try v.end(f, inst, w); @@ -4906,11 +4903,9 @@ fn lowerSwitchCmp( fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { const dg = f.dg; - const target = &dg.mod.resolved_target.result; return switch (constraint[0]) { '{' => true, - 'i', 'r' => false, - 'I' => !target.cpu.arch.isArm(), + 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false, else => switch (value) { .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { @@ -4937,10 +4932,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { - const inst_local = try f.allocLocalValue(.{ - .type = inst_ty, - .alignment = .none, - }); + const inst_local = try f.allocLocalValue(.{ .type = inst_ty }); if (f.wantSafety()) { try f.writeCValue(w, inst_local, .other); try w.writeAll(" = "); @@ -4967,10 +4959,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (is_reg) { const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); try w.writeAll("register "); - const output_local = try f.allocLocalValue(.{ - .type = output_ty, - .alignment = .none, - }); + const output_local = try f.allocLocalValue(.{ .type = output_ty }); try f.allocs.put(gpa, output_local.new_local, false); try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); try w.writeAll(" __asm(\""); @@ -5000,10 +4989,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (asmInputNeedsLocal(f, constraint, input_val)) { const input_ty = f.typeOf(input.operand); if (is_reg) try w.writeAll("register "); - const input_local = try f.allocLocalValue(.{ - .type = input_ty, - .alignment = .none, - }); + const input_local = try f.allocLocalValue(.{ .type = input_ty }); try f.allocs.put(gpa, input_local.new_local, false); // Do not render the declaration as `const` qualified if we're generating an // explicit `register` local, as GCC will ignore the constraint completely. @@ -5853,28 +5839,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { else unreachable; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_operand = lowersToBigInt(scalar_ty, zcu); + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_intCast_{c}{d}", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); + try w.writeAll("(&"); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } else { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try w.writeAll("zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); - try w.writeByte('('); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); } try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } + if (ref_operand) { + const operand_int_info = scalar_ty.intInfo(zcu); + if (operand_int_info.bits <= 128) { + try w.print("zig_{c}{d}_intCast_", .{ + @as(u8, switch (operand_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)), + }); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try w.writeAll("(&"); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, scalar_ty, .none); + try w.writeByte(')'); + } else { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + operand_int_info.bits, + false, + 10, + .lower, + )}); + } + } else { + try f.writeCValue(w, operand, .other); + try v.elem(f, w); + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + inst_int_info.bits, + false, + 10, + .lower, + )}); + } try w.writeByte(')'); if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); - try w.writeByte(')'); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.print(", {f}", .{ + try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other), + }); + try w.writeByte(')'); + } + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none); + try w.writeByte(')'); + } } try w.writeByte(';'); try f.newline(); @@ -5893,18 +5975,21 @@ fn airUnBuiltinCall( const pt = f.dg.pt; const zcu = pt.zcu; - const operand = try f.resolveInst(operand_ref); - try reap(f, inst, &.{operand_ref}); const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(operand_ref); const scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); + + const operand = try f.resolveInst(operand_ref); + if (!is_big) try reap(f, inst, &.{operand_ref}); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); const ref_arg = lowersToBigInt(scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{operand_ref}); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); @@ -5920,8 +6005,13 @@ fn airUnBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, operand, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");"); @@ -5941,8 +6031,9 @@ fn airBinBuiltinCall( const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - const is_big = lowersToBigInt(operand_ty, zcu); + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -5950,22 +6041,31 @@ fn airBinBuiltinCall( const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const v = try Vectorize.start(f, inst, w, operand_ty); + const v = try Vectorize.start(f, inst, w, lhs_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } try w.print("zig_{s}_", .{operation}); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); + switch (info) { + .bits, .none, .big_temp_bits => {}, + .bits_none => { + try w.writeByte('_'); + try f.dg.renderTypeForBuiltinFnName(w, rhs_scalar_ty); + }, + } try w.writeByte('('); if (ref_ret) { try w.writeByte('&'); @@ -5973,15 +6073,45 @@ fn airBinBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); - try w.writeAll(");\n"); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) { + .none => .none, + .bits, .bits_none => .bits, + .big_temp_bits => { + if (lowersToBigInt(lhs_scalar_ty, zcu)) { + const temp_local = try f.allocAlignedLocal(inst, .{ + .type = lhs_scalar_ty, + .array_len = 2, + }); + try w.writeAll(", &"); + try f.writeCValue(w, temp_local, .other); + try freeLocal(f, inst, temp_local.new_local, null); + } + break :info .none; + }, + }); + switch (info) { + .none, .bits, .big_temp_bits => {}, + .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none), + } + try w.writeAll(");"); + try f.newline(); try v.end(f, inst, w); return local; @@ -6029,12 +6159,22 @@ fn airCmpBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeByte(')'); @@ -6595,7 +6735,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { }, .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other), } - try w.writeAll(";\n"); + try w.writeByte(';'); + try f.newline(); } return local; @@ -6653,7 +6794,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(reduce.operand); const w = &f.code.writer; - const use_operator = scalar_ty.bitSize(zcu) <= 64; + const use_operator, const is_big = if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => .{ true, false }, + .zig_u128, .zig_i128 => .{ false, false }, + }, + .big => .{ false, true }, + } else .{ false, false }; const op: union(enum) { const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; builtin: Func, @@ -6742,25 +6890,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { try f.newline(); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, accum, .other); switch (op) { .builtin => |func| { - try w.print(" = zig_{s}_", .{func.operation}); + const prev_accum = if (is_big) prev_accum: { + const prev_accum = try f.allocLocal(inst, scalar_ty); + try f.writeCValue(w, prev_accum, .other); + try w.writeAll(" = "); + try f.writeCValue(w, accum, .other); + try w.writeByte(';'); + try f.newline(); + break :prev_accum prev_accum; + } else prev_accum: { + try f.writeCValue(w, accum, .other); + try w.writeAll(" = "); + break :prev_accum accum; + }; + try w.print("zig_{s}_", .{func.operation}); try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); - try f.writeCValue(w, accum, .other); + if (is_big) { + try w.writeByte('&'); + switch (accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, accum, .other), + } + try w.writeAll(", &"); + switch (prev_accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, prev_accum, .other), + } + } else try f.writeCValue(w, prev_accum, .other); try w.writeAll(", "); - try f.writeCValue(w, operand, .other); + if (is_big) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); try w.writeByte(')'); + if (is_big) try freeLocal(f, inst, prev_accum.new_local, null); }, .infix => |ass| { + try f.writeCValue(w, accum, .other); try w.writeAll(ass); try f.writeCValue(w, operand, .other); try v.elem(f, w); }, .ternary => |cmp| { + try f.writeCValue(w, accum, .other); try w.writeAll(" = "); try f.writeCValue(w, accum, .other); try w.writeAll(cmp); @@ -7224,17 +7404,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 { fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 { return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { + 0 => unreachable, 1...32 => "si", 33...64 => "di", 65...128 => "ti", - else => unreachable, + else => "ei", } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + else => unreachable, 16 => "hf", 32 => "sf", 64 => "df", 80 => "xf", - 128 => "tf", - else => unreachable, + 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf", } else unreachable; } @@ -7390,10 +7571,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont return .{ .data = .{ .str = str, .sentinel = sentinel } }; } -fn undefPattern(comptime IntType: type) IntType { - const int_info = @typeInfo(IntType).int; - const UnsignedType = @Int(.unsigned, int_info.bits); - return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); +fn undefPattern(comptime Result: type) Result { + return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3)); } const FormatIntLiteralContext = struct { @@ -7580,11 +7759,9 @@ const FormatSignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); - const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); - if (data.val == max_int) { + if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); - } else if (data.val == min_int) { + } else if (data.val == @as(i64, std.math.minInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); } if (data.val < 0) try w.writeByte('-'); @@ -7596,7 +7773,7 @@ const FormatSignedIntLiteralSmall = struct { 16 => try w.writeAll("0x"), else => unreachable, } - // This `@abs` is safe thanks to the `min_int` case above. + // This `@abs` is safe thanks to the min int check above. try w.printInt(@abs(data.val), data.base, data.case, .{}); try w.writeAll(intLiteralSuffix(data.int_cty)); } @@ -7610,8 +7787,7 @@ const FormatUnsignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); - if (data.val == max_int) { + if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); } try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); @@ -7735,6 +7911,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 { }; } +const F80Repr = packed struct { + mantissa: u64, + exponent: u16, + + fn write(repr: F80Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f80({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.mantissa, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint16_t, repr.exponent, is_global, 16, .lower), + }); + } +}; +const F128Repr = packed struct { + lo: u64, + hi: u64, + + fn write(repr: F128Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f128({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.hi, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.lo, is_global, 16, .lower), + }); + } +}; + const Materialize = struct { local: CValue, diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index 866ea38cc44be5a44e0dba9aa6c75cf989cb664b..bfa368d3ceee36ac575898019e1b48d19a20d066 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -21,16 +21,21 @@ pub fn defineAligned( if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); } - try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{ + try w.print("{f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{ alignment.toByteUnits().?, ty.fmt(pt), }); + try w.writeByte('\n'); } /// Renders the definition of a big-int `struct`. pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const target = zcu.getTarget(); + const bits = big.limb_size.bits() *| big.limbs_len; const name_cty: CType = .{ .bigint = .{ .limb_size = big.limb_size, .limbs_len = big.limbs_len, @@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error .elem_ty = &limb_cty, .nonstring = limb_cty.isStringElem(), } }; - try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{ + try w.print("{f} {{ {f}limbs{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - big.limb_size.bits() * @as(u17, big.limbs_len), }); + if (!zcu.comp.config.root_strip) try w.print(" /* u{d}, i{d} */", .{ bits, bits }); + try w.writeByte('\n'); + try writeStaticAssertCTypeLayout( + name_cty, + std.zig.target.intByteSize(target, bits), + .fromByteUnits(std.zig.target.intAlignment(target, bits)), + w, + zcu, + ); } /// Renders a forward declaration of the `struct` which represents an error union whose payload type @@ -81,27 +94,28 @@ pub fn errunionDefineComplete( if (payload_ty.hasRuntimeBits(zcu)) { const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); try w.print( - \\{f} {{ /* anyerror!{f} */ + \\{f} {{ \\ {f}payload{f}; \\ {f}error{f}; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - payload_ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), }); } else { - try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ + try w.print("{f} {{ {f}error{f}; }};", .{ name_cty.fmtTypeName(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), - payload_ty.fmt(pt), }); } + if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{ + payload_ty.fmt(pt), + }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that @@ -141,10 +155,13 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo }, else => return, }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ ty.fmt(pt), }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the @@ -163,13 +180,13 @@ pub fn defineComplete( ty.assertHasLayout(zcu); - switch (ty.zigTypeTag(zcu)) { + const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) { .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { const name_cty: CType = .{ .@"fn" = ty }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); + break :check_cty null; } else { const ip = &zcu.intern_pool; const func_type = ip.indexToKey(ty.toIntern()).func_type; @@ -205,82 +222,82 @@ pub fn defineComplete( } else if (!any_params) { try w.writeAll("void"); } - try w.print("){f}; /* {f} */\n", .{ + try w.print("){f};", .{ ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), - ty.fmt(pt), }); + break :check_cty null; }, .@"enum" => { const name_cty: CType = .{ .@"enum" = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + break :check_cty null; }, - .@"struct" => if (ty.isTuple(zcu)) { - try defineTuple(ty, deps, arena, w, pt); - } else switch (ty.containerLayout(zcu)) { - .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), + .@"struct" => if (ty.isTuple(zcu)) + if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return + else switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .@"union" => switch (ty.containerLayout(zcu)) { - .auto => try defineUnionAuto(ty, deps, arena, w, pt), - .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), + .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return, + .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .pointer => if (ty.isSlice(zcu)) { const name_cty: CType = .{ .slice = ty }; const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}ptr{f}; \\ size_t len; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), ptr_cty.fmtDeclaratorPrefix(zcu), ptr_cty.fmtDeclaratorSuffix(zcu), }); - // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess - // slices up, and they're all obviously the same layout. - }, + break :check_cty switch (ty.toIntern()) { + .slice_const_u8_sentinel_0_type => name_cty, + else => null, + }; + } else return, .optional => switch (CType.classifyOptional(ty, zcu)) { .error_set, .ptr_like, .slice_like, .npv_payload, - => {}, + => return, .opv_payload => { const name_cty: CType = .{ .opt = ty }; - try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{ + try w.print("{f} {{ bool is_null; }};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty switch (ty.toIntern()) { + .optional_noreturn_type => name_cty, + else => null, + }; }, .@"struct" => { const name_cty: CType = .{ .opt = ty }; const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}payload{f}; \\ bool is_null; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty name_cty; }, }, .array => if (ty.hasRuntimeBits(zcu)) { @@ -295,14 +312,13 @@ pub fn defineComplete( break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); }, } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, + break :check_cty name_cty; + } else return, .vector => if (ty.hasRuntimeBits(zcu)) { const name_cty: CType = .{ .vec = ty }; const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); @@ -311,16 +327,20 @@ pub fn defineComplete( .elem_ty = &elem_cty, .nonstring = elem_cty.isStringElem(), } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, - else => {}, - } + break :check_cty name_cty; + } else return, + else => return, + }; + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ + ty.fmt(pt), + }); + try w.writeByte('\n'); + if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu); } fn defineBitpack( ty: Type, @@ -328,16 +348,16 @@ fn defineBitpack( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!?CType { const zcu = pt.zcu; const name_cty: CType = .{ .bitpack = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + return null; } fn defineTuple( ty: Type, @@ -345,9 +365,8 @@ fn defineTuple( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const tuple = ip.indexToKey(ty.toIntern()).tuple_type; @@ -367,9 +386,8 @@ fn defineTuple( } else true; const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var zig_offset: u64 = 0; var c_offset: u64 = 0; @@ -403,9 +421,8 @@ fn defineTuple( zig_offset += field_size; c_offset += field_size; } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineStruct( ty: Type, @@ -413,9 +430,8 @@ fn defineStruct( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const struct_type = ip.loadStructType(ty.toIntern()); @@ -457,9 +473,8 @@ fn defineStruct( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var it = struct_type.iterateRuntimeOrder(ip); var offset: u64 = 0; @@ -497,9 +512,8 @@ fn defineStruct( assert(struct_type.alignment.forward(offset) == struct_type.size); try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } fn defineUnionAuto( ty: Type, @@ -507,9 +521,8 @@ fn defineUnionAuto( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -553,9 +566,8 @@ fn defineUnionAuto( const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); const name_cty: CType = .{ .union_auto = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); if (payload_has_bits) { try w.writeByte(' '); @@ -587,9 +599,8 @@ fn defineUnionAuto( tag_cty.fmtDeclaratorSuffix(zcu), }); } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineUnionExtern( ty: Type, @@ -597,9 +608,8 @@ fn defineUnionExtern( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -636,9 +646,8 @@ fn defineUnionExtern( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .union_extern = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { @@ -659,9 +668,8 @@ fn defineUnionExtern( } try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } /// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, @@ -680,19 +688,29 @@ fn writeFieldAlign( } /// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. -fn writeStaticAssertLayout( +pub fn writeStaticAssertTypeLayout( ty: Type, cty: CType, w: *Writer, zcu: *const Zcu, +) Writer.Error!void { + try writeStaticAssertCTypeLayout(cty, ty.abiSize(zcu), ty.abiAlignment(zcu), w, zcu); +} + +/// Emits static assertions that the size and alignment of `cty` match the provided values. +pub fn writeStaticAssertCTypeLayout( + cty: CType, + expected_size: u64, + expected_alignment: Alignment, + w: *Writer, + zcu: *const Zcu, ) Writer.Error!void { try w.print( - \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); - \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); + \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch"); \\ , .{ - cty.fmtTypeName(zcu), ty.abiSize(zcu), - cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, + cty.fmtTypeName(zcu), expected_size, + cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?, }); } diff --git a/src/link.zig b/src/link.zig index 7ce8363a3d77d9191b813cc86f2896e0285bec4e..15d9fcb513a8b329d6ebfbc6cf66d92b02352bc8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1238,7 +1238,7 @@ pub const File = struct { } switch (base.tag) { - inline .elf2, .coff2, .wasm => |tag| { + inline .elf2, .coff2, .wasm, .c => |tag| { dev.check(tag.devFeature()); try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); }, diff --git a/src/link/C.zig b/src/link/C.zig index a6830126fb2f048af065093adf6e99e2778e0c88..cf82ed146fa853cc449074721eb294834cde6d1b 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index), /// one array. align_dependency_masks: std.ArrayList(u64), +/// Emitted at the top of the file. This can be cached since it only depends on the target. +header: String, /// All NAVs, regardless of whether they are functions or simple constants, are put in this map. navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl), /// All UAVs which may be referenced are in this map. The UAV alignment is not included in the @@ -404,9 +406,8 @@ pub fn createEmpty( emit: Path, options: link.File.OpenOptions, ) !*C { + assert(comp.root_mod.resolved_target.result.ofmt == .c); const io = comp.io; - const target = &comp.root_mod.resolved_target.result; - assert(target.ofmt == .c); const optimize_mode = comp.root_mod.optimize_mode; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -422,9 +423,8 @@ pub fn createEmpty( }); errdefer file.close(io); - const c_file = try arena.create(C); - - c_file.* = .{ + const c = try arena.create(C); + c.* = .{ .base = .{ .tag = .c, .comp = comp, @@ -439,6 +439,7 @@ pub fn createEmpty( .string_bytes = .empty, .type_dependencies = .empty, .align_dependency_masks = .empty, + .header = .empty, .navs = .empty, .uavs = .empty, .type_pool = .empty, @@ -447,8 +448,7 @@ pub fn createEmpty( .exported_navs = .empty, .exported_uavs = .empty, }; - - return c_file; + return c; } pub fn deinit(c: *C) void { @@ -469,6 +469,21 @@ pub fn deinit(c: *C) void { c.exported_uavs.deinit(gpa); } +pub fn prelink(c: *C, prog_node: std.Progress.Node) !void { + const comp = c.base.comp; + + const sub_prog_node = prog_node.start("Generate Header", 0); + defer sub_prog_node.end(); + + var header_aw: std.Io.Writer.Allocating = .init(comp.gpa); + defer header_aw.deinit(); + codegen.genHeader(comp.zcu.?, &header_aw.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + else => |e| return e, + }; + c.header = try c.addString(&.{header_aw.written()}); +} + pub fn updateContainerType( c: *C, pt: Zcu.PerThread, @@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog const io = comp.io; const zcu = c.base.comp.zcu.?; const ip = &zcu.intern_pool; - const target = zcu.getTarget(); const active = zcu.activate(tid); defer active.deactivate(); const pt = active.pt; @@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin // to build the output buffer. Our strategy is to emit the C source in this order: // - // * ABI defines and `#include "zig.h"` + // * Header // * Big-int type definitions // * Other CType definitions (traversing the dependency graph to sort topologically) // * Global assembly @@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! - try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` + try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header 1 + // Big-int type definitions need_types.count() + // `RenderedType.fwd_decl` (worst-case) need_types.count() + // `RenderedType.definition` @@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "") need_navs.count() * 2); // NAV definitions ("static ", "") - // ABI defines and `#include "zig.h"` - switch (target.abi) { - .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), - else => {}, - } - f.appendBufAssumeCapacity(try std.fmt.allocPrint( - arena, - "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", - .{target.cMaxIntAlignment()}, - )); - f.appendBufAssumeCapacity( - \\#include "zig.h" - \\ - ); + f.appendBufAssumeCapacity(c.header.get(c)); // Big-int type definitions var bigint_aw: std.Io.Writer.Allocating = .init(gpa); diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig index 895f9bbf8d956e61bdf5455084cd4d58ebd2b1e9..9c140d35499fe43c6dfb1b5309e4dbd8bd7263c0 100644 --- a/test/behavior/abs.zig +++ b/test/behavior/abs.zig @@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try comptime testAbsSignedBigInt(); try testAbsSignedBigInt(); @@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void { test "@abs int vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 9ffb238dfdb9994bf587b7e4e4b5743842dbcc4c..957ac6b1796c3ce962c139fc3669c4760c8ede87 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -547,7 +547,6 @@ test "sub-aligned pointer field access" { } test "alignment of zero-bit types is respected" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -582,7 +581,6 @@ test "zero-bit fields in extern struct pad fields appropriately" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = extern struct { x: u8, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 16fdfc8c15cbd9f5e9ad3cc11d72461092cf839c..964de5d20ff8754e81d3c0deae59fd44a672b6f8 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -800,7 +800,6 @@ test "extern variable with non-pointer opaque type" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO @export(&var_to_export, .{ .name = "opaque_extern_var" }); diff --git a/test/behavior/bit_shifting.zig b/test/behavior/bit_shifting.zig index 9eed252ac8ddc055038a0bf227616f3df49369bd..a9d81b6b53e6d1761e99234200fdcc155e2efa1f 100644 --- a/test/behavior/bit_shifting.zig +++ b/test/behavior/bit_shifting.zig @@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" { test "Saturating Shift Left" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index b3b64af19b9d99ed922ec087209d02ecab14354a..785daa0d3194b00d43c00760a11199075d9377dd 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element test "@bitCast packed struct of floats" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" { test "comptime @bitCast packed struct to int and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" { test "bitcast vector to integer and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 { } test "bitcast nan float does not modify signaling bit" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const snan_u16: u16 = 0x7D00; const snan_u32: u32 = 0x7FA00000; @@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" { test "@bitCast of packed struct of bools all true" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" { test "@bitCast of packed struct of bools all false" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO const P = packed struct { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 0117c647880eb21fb9226abfc816a22ad2bcd2a7..4cbe2f1aed593d513d58691ec7baf5613494f9e7 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -134,7 +134,6 @@ test "@intFromFloat > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testIntFromFloat(f16, 1024, u140, 1024); try testIntFromFloat(f16, -1024, i140, -1024); @@ -160,7 +159,6 @@ test "@floatFromInt > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testFloatFromInt(u140, 1024, f16, 1024); try testFloatFromInt(i140, -1024, f16, -1024); @@ -182,7 +180,6 @@ test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -281,6 +278,7 @@ test "type coercion from int to float" { test "@intFromFloat" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + try testIntFromFloats(); try comptime testIntFromFloats(); } @@ -1473,11 +1471,6 @@ fn foobar(func: PFN_void) !void { test "cast function with an opaque parameter" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) { - // https://github.com/ziglang/zig/issues/16845 - return error.SkipZigTest; - } - const Container = struct { const Ctx = opaque {}; ctx: *Ctx, @@ -1724,7 +1717,6 @@ test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; @@ -1831,7 +1823,6 @@ test "pointer to empty struct literal to mutable slice" { test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index 34adedf7267030379ee573cb519ce6dbe29c95e3..50a1b74d8ab76bdccf8b04795a04ca77bdee078b 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -168,7 +168,6 @@ test "@intCast <= 64 bits" { test "@intCast > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testIntCast(u8, 123, u140, 123); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 60a06886d45ac988b55d0a51f5bc40101f098e7e..f86ab963d2a4ea5dd0cec5493f583ac672a174e7 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -513,7 +513,6 @@ test "runtime 128 bit integer division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: u128 = 152313999999999991610955792383; diff --git a/test/behavior/extern.zig b/test/behavior/extern.zig index 4de68589468790419a9e993fd68caf2f20e6eae9..ed95406aa889d361abbf87a79764eb23d62021ca 100644 --- a/test/behavior/extern.zig +++ b/test/behavior/extern.zig @@ -3,7 +3,6 @@ const std = @import("std"); const expect = std.testing.expect; test "anyopaque extern symbol" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index 85250c54ad7d083be1a2f132b7fdc0a2785e10b2..c3d0c0087cc7eb9694310d5f8ff3755e35ca8077 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { } test "@fieldParentPtr unaligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" { } test "@fieldParentPtr aligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index f8fbab0aaefd3d3d4b39d472eb84e41b9382dc8f..7e9f58e46b0cfa6632234c2136344da6240f468f 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -142,7 +142,6 @@ test "cmp f64" { test "cmp f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -152,7 +151,6 @@ test "cmp f128" { test "cmp f80/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -253,7 +251,6 @@ test "vector cmp f64" { test "vector cmp f128" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest; @@ -1055,7 +1052,6 @@ test "@abs f32/f64" { test "@abs f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1173,7 +1169,6 @@ test "@floor f32/f64" { test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1262,7 +1257,6 @@ test "@ceil f32/f64" { test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1282,7 +1276,6 @@ test "@ceil f80/f128/c_longdouble" { test "@ceil f80 maxInt(u64)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1369,7 +1362,6 @@ test "@trunc f32/f64" { test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 14cb20f5442a452695ccad2134bd4d0c306ab4b2..47e6be86bb715f90bae1eb08a9237af2f07c1515 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn { test "extern struct with stdcallcc fn pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = extern struct { diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 22b91be640579e1e8fe460f4652f998c5c1b9b6d..8750c7723149a9c772ec2dae6aaeda0b4ba03f8b 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -873,7 +873,6 @@ test "umax wrapped squaring" { test "128-bit multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; { @@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testAddWithOverflow(u129, 4, 105, 109, 0); try testAddWithOverflow(u129, 1000, 100, 1100, 0); @@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" { test "@mulWithOverflow bitsize 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" { test "@mulWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0); @@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" { test "@mulWithOverflow bitsize 256 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1); try testSubWithOverflow(u129, 1000, 100, 900, 0); @@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" { test "@shlWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0); @@ -1419,7 +1412,6 @@ fn testAnd(comptime T: type, a: T, b: T, expected: T) !void { test "and > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88); try testAnd(u140, maxInt(u140), 1 << 100, 1 << 100); @@ -1448,7 +1440,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void { test "or > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testOr(u140, 0, 1 << 139, 1 << 139); try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf); @@ -1477,7 +1468,6 @@ fn testXor(comptime T: type, a: T, b: T, expected: T) !void { test "xor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testXor(u140, 0, maxInt(u140), maxInt(u140)); try testXor(u140, 1 << 139, 1 << 139, 0); @@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void { test "not > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testNot(u140, 0, maxInt(u140)); try testNot(u140, maxInt(u140), 0); @@ -1535,7 +1524,6 @@ fn testShl(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShl(u140, 1 << 5, 10, 1 << 15); try testShl(u140, 3, 138, (1 << 139) | (1 << 138)); @@ -1564,7 +1552,6 @@ fn testShr(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shr > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShr(u140, 1 << 139, 39, 1 << 100); try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1); @@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void { test "@clz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testClz(u140, 0, 140); @@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void { test "@ctz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testCtz(u140, 0, 140); @@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void { test "@popCount > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testPopCount(u140, 0, 0); @@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void { test "@bitReverse > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testBitReverse(u140, 1 << 139, 1); @@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void { test "@byteSwap > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testByteSwap(u144, 1 << 136, 1); @@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void { test "@max > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMax(u140, 0, maxInt(u140), maxInt(u140)); @@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void { test "@min > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMin(u140, 0, maxInt(u140), 0); @@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void { test "@abs > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAbs(u140, 0, 0); try testAbs(u140, 1 << 139, 1 << 139); @@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@rem > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testRem(u140, 0, maxInt(u140), 0); @@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@mod > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMod(u140, 0, maxInt(u140), 0); @@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divFloor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivFloor(u140, 0, maxInt(u140), 0); @@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi test "@divCeil > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivCeil(u140, 0, maxInt(u140), 0); @@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divTrunc > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivTrunc(u140, 0, maxInt(u140), 0); @@ -2166,7 +2140,6 @@ test "remainder division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { @@ -2315,7 +2288,6 @@ test "@round f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f80, 12.0); @@ -2326,7 +2298,6 @@ test "@round f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f128, 12.0); diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index 22db5a75502f8456ac0637ef134a137434d3da75..533f44869573a924e50a08b3806a03c4243fc7ee 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -115,7 +115,6 @@ test "@min/max for floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig index 086a325bd6246dd660641aec924c20339494f8a2..bde6459e849c14384d69fc57811f59b747a0f2de 100644 --- a/test/behavior/muladd.zig +++ b/test/behavior/muladd.zig @@ -49,7 +49,6 @@ test "@mulAdd f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd80(); @@ -68,7 +67,6 @@ test "@mulAdd f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd128(); @@ -169,7 +167,6 @@ test "vector f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector80(); @@ -194,7 +191,6 @@ test "vector f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector128(); diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 96585d056cdf4c13b1aff3610ad08088fc0bf61c..045c19767454b64d970fe6c7a46dafcb9b2a1ac4 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -404,7 +404,6 @@ test "nested packed struct field pointers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO const S2 = packed struct { base: u8, @@ -579,7 +578,6 @@ test "packed struct fields modification" { } test "nested packed struct field access test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -1171,7 +1168,6 @@ test "packed struct equality" { test "packed struct equality ignores padding bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = packed struct { b: bool }; diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 9ac875fad4990e03554fc217fb38f42d0dfa6e62..807f4f5450d3fb372e18e2fc78f71fea9ce4d5bb 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" { } test "allowzero pointer and slice" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/saturating_arithmetic.zig b/test/behavior/saturating_arithmetic.zig index c434f014f36e40f2cfea9fc0c2508320d09c74a4..c5fa221c124d4113a73db22ab33778e521a9c52a 100644 --- a/test/behavior/saturating_arithmetic.zig +++ b/test/behavior/saturating_arithmetic.zig @@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testSatMul(u8, 0, maxInt(u8), 0); @@ -238,7 +237,6 @@ test "saturating multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -313,7 +311,6 @@ test "saturating shift-left" { test "saturating shift-left large rhs" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; @@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" { test "sat add > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatAdd(u140, 0, 0, 0); @@ -377,7 +373,6 @@ test "sat add > 128 bits" { test "sat sub > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatSub(u140, 0, 1, 0); @@ -393,7 +388,6 @@ test "sat sub > 128 bits" { test "sat mul > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatMul(u140, 0, maxInt(u140), 0); @@ -409,7 +403,6 @@ test "sat mul > 128 bits" { test "sat shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatShl(u140, 0, u8, 17, 0); diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 379e5ec18343c226b0e2d67b1dca8b8d53f13340..2aa7920ab4b17ae56df165a880d3242e3a3fedb0 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -535,7 +535,6 @@ test "zero-bit field in packed struct" { test "packed struct with non-ABI-aligned field" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const U = union(enum) { @@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" { } test "struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" { } test "extern struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" { } test "struct containing optional pointer to array of @This()" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { @@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" { test "struct contains underaligned field with overaligned pointer to itself" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { ptr: *align(8) @This() align(1), }; diff --git a/test/behavior/switch_loop.zig b/test/behavior/switch_loop.zig index 9f4859789c9c3f23488ae0814c67b132112a3335..caaea13e7f8aa3571a0f3f34c7b05b0ee37eea3b 100644 --- a/test/behavior/switch_loop.zig +++ b/test/behavior/switch_loop.zig @@ -223,7 +223,6 @@ test "unanalyzed continue with operand" { test "switch loop on larger than pointer integer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined; @@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" { test "switch loop with discarded tag capture" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { const U = union(enum) { a: u32, diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index 07d19f29c0da73a045ae58d35836502cbebe5cdc..506a0d2bea99b768c6761cc3da31558b88eddf11 100644 --- a/test/behavior/truncate.zig +++ b/test/behavior/truncate.zig @@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void { test "@truncate > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testTruncate(u140, 0, u128, 0); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 340f7006e72b7f48ecaf7280cd9cd982f8600060..8ed483d02278160bc13f52b60a6b5cf5344eb40e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" { } test "defined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" { } test "undefined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1758,8 +1756,6 @@ test "reinterpret packed union" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } @@ -1800,8 +1796,6 @@ test "reinterpret packed union inside packed struct" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 7d63b136fda14fca1358123c1546820a42f0dcf9..9f8d277774f278dd2e7ee138e5d54e52fbfaa491 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -128,7 +128,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { // Triggers an assertion with LLVM 18: @@ -736,7 +735,6 @@ test "vector reduce operation" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562 @@ -1437,7 +1435,6 @@ test "store packed vector element" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var v = @Vector(4, u1){ 1, 1, 1, 1 }; @@ -1469,7 +1466,6 @@ test "store vector with memset" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: [5]@Vector(2, i1) = undefined; @@ -1610,7 +1606,6 @@ test "bitcast vector to array of smaller vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const u8x32 = @Vector(32, u8); const u8x64 = @Vector(64, u8); diff --git a/test/standalone/build.zig b/test/standalone/build.zig index dc8d85d399477256b65c60dc1b4850144c641738..f14d17562d4715ca75340d67b6b2ce5b7344b73d 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -39,7 +39,6 @@ pub fn build(b: *std.Build) void { "../../tools/gen_parser_oracle.zig", "../../tools/gen_spirv_spec.zig", "../../tools/gen_stubs.zig", - "../../tools/generate_c_size_and_align_checks.zig", "../../tools/generate_JSONTestSuite.zig", "../../tools/generate_linux_syscalls.zig", "../../tools/process_headers.zig", diff --git a/test/tests.zig b/test/tests.zig index 9a11d7c496a5179e02c74969f4481034764baa55..849267617f0cfe5e8c8f227a3758a397ba047083 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -274,6 +274,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -292,6 +301,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -341,6 +359,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -360,6 +387,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -1107,6 +1143,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .linux, + .abi = .musl, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .x86, @@ -1645,6 +1690,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .windows, + .abi = .gnu, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ @@ -2782,16 +2836,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const target = &resolved_target.result; - if (target.cpu.arch == .s390x and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/35523 - continue; - } - - if (target.cpu.arch == .riscv64 and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/30930 - continue; - } - if (std.mem.eql(u8, options.name, "libc")) { // The libc API tests obviously need to link libc. So for test // target entries where we wouldn't link libc by default, skip the diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig deleted file mode 100644 index 09400615f2c526bdde3ce99c62b0f5a0bf386932..0000000000000000000000000000000000000000 --- a/tools/generate_c_size_and_align_checks.zig +++ /dev/null @@ -1,62 +0,0 @@ -//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple] -//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu -//! -//! Prints _Static_asserts for the size and alignment of all the basic built-in C -//! types. The output can be run through a compiler for the specified target to -//! verify that Zig's values are the same as those used by a C compiler for the -//! target. - -const std = @import("std"); -const Io = std.Io; - -fn cName(ty: std.Target.CType) []const u8 { - return switch (ty) { - .char => "char", - .short => "short", - .ushort => "unsigned short", - .int => "int", - .uint => "unsigned int", - .long => "long", - .ulong => "unsigned long", - .longlong => "long long", - .ulonglong => "unsigned long long", - .float => "float", - .double => "double", - .longdouble => "long double", - }; -} - -var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init; - -pub fn main(init: std.process.Init) !void { - const args = try init.minimal.args.toSlice(init.arena.allocator()); - const io = init.io; - - if (args.len != 2) { - std.debug.print("Usage: {s} [target_triple]\n", .{args[0]}); - std.process.exit(1); - } - - const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); - const target = try std.zig.system.resolveTargetQuery(io, query); - - var buffer: [2000]u8 = undefined; - var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer); - const w = &stdout_writer.interface; - inline for (@typeInfo(std.Target.CType).@"enum".field_values) |field_value| { - const c_type: std.Target.CType = @fromBackingInt(@intCast(field_value)); - try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeByteSize(c_type), - }); - try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeAlignment(c_type), - }); - try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{ - cName(c_type), - target.cTypePreferredAlignment(c_type), - }); - } - try w.flush(); -} -- 2.54.0 From b425e6869452ebeaf9b15ceb5739ce4b4bb5b87d Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 24 Jun 2026 19:34:13 -0400 Subject: [PATCH 053/215] llvm: update for compiler_rt abi changes Closes #12602 Closes #21234 Closes #35899 Closes #36127 --- lib/compiler/aro/aro/Target.zig | 6 +- lib/compiler/reduce.zig | 2 +- lib/compiler/test_runner.zig | 21 +- lib/compiler_rt/comparef.zig | 2 +- lib/std/Io/Writer.zig | 12 +- lib/std/Target.zig | 34 +- lib/std/math/gamma.zig | 2 - lib/std/zig/llvm/Builder.zig | 4 +- lib/std/zig/target.zig | 36 +- src/Sema.zig | 8 +- src/Sema/type_resolution.zig | 2 +- src/Type.zig | 184 +-- src/Value.zig | 7 +- src/codegen/aarch64/Select.zig | 2 +- src/codegen/aarch64/abi.zig | 7 +- src/codegen/arm/abi.zig | 16 +- src/codegen/c/type.zig | 36 +- src/codegen/c/type/render_defs.zig | 26 +- src/codegen/llvm.zig | 936 +++++++++----- src/codegen/llvm/FuncGen.zig | 1919 ++++++++++++++++------------ src/codegen/mips/abi.zig | 9 +- src/codegen/riscv64/CodeGen.zig | 4 +- src/codegen/riscv64/abi.zig | 12 +- src/codegen/s390x/abi.zig | 8 +- src/codegen/wasm/CodeGen.zig | 24 +- src/codegen/wasm/abi.zig | 6 +- src/codegen/x86_64/CodeGen.zig | 18 +- src/codegen/x86_64/abi.zig | 12 +- src/libs/mingw/Preprocessor.zig | 4 +- src/target.zig | 4 +- test/behavior/align.zig | 40 +- test/behavior/cast.zig | 3 +- test/behavior/floatop.zig | 22 - test/behavior/math.zig | 6 - test/behavior/vector.zig | 24 +- test/c_abi/cfuncs.c | 10 +- test/c_abi/main.zig | 141 +- test/tests.zig | 6 - 38 files changed, 2141 insertions(+), 1474 deletions(-) diff --git a/lib/compiler/aro/aro/Target.zig b/lib/compiler/aro/aro/Target.zig index 3a871504700f666b6e74ca464d37c0770568c43d..a0c9f3be3943810313dfcd94b94f6bea0794ff2d 100644 --- a/lib/compiler/aro/aro/Target.zig +++ b/lib/compiler/aro/aro/Target.zig @@ -1559,15 +1559,15 @@ pub fn ptrBitWidth(target: *const Target) u16 { } pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { - return target.toZigTarget().cCharSignedness(); + return target.toZigTarget().cCharSignedness().?; } pub fn cTypeBitSize(target: *const Target, c_type: std.Target.CType) u16 { - return target.toZigTarget().cTypeBitSize(c_type); + return target.toZigTarget().cTypeBitSize(c_type).?; } pub fn cTypeAlignment(target: *const Target, c_type: std.Target.CType) u16 { - return target.toZigTarget().cTypeAlignment(c_type); + return target.toZigTarget().cTypeAlignment(c_type).?; } pub fn standardDynamicLinkerPath(target: *const Target) std.Target.DynamicLinker { diff --git a/lib/compiler/reduce.zig b/lib/compiler/reduce.zig index 04f0c03650031d0083cd84f89fa87bfa7b8aff09..398a44a9b4e1d9ec0670db4cd0d2878c37ff6c83 100644 --- a/lib/compiler/reduce.zig +++ b/lib/compiler/reduce.zig @@ -400,7 +400,7 @@ fn parse(gpa: Allocator, io: Io, file_path: []const u8) !Ast { file_path, gpa, .limited(std.math.maxInt(u32)), - .fromByteUnits(1), + .@"1", 0, ) catch |err| { fatal("unable to open '{s}': {s}", .{ file_path, @errorName(err) }); diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 4e9502656c56f1e8cc43a03529d5d2599abbace5..2827d32c496e12c3a2bf7c481b54afa50eb477fe 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void { return std.process.exit(0); }, .query_test_metadata => { - testing.allocator_instance = .init(std.heap.page_allocator, .{}); - defer if (testing.allocator_instance.deinit() != 0) { - @panic("internal test runner memory leak"); - }; + var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); + defer if (sa.deinit() != 0) @panic("internal test runner memory leak"); + const gpa = sa.allocator(); var string_bytes: std.ArrayList(u8) = .empty; - defer string_bytes.deinit(testing.allocator); - try string_bytes.append(testing.allocator, 0); // Reserve 0 for null. + defer string_bytes.deinit(gpa); + try string_bytes.append(gpa, 0); // Reserve 0 for null. const test_fns = builtin.test_functions; - const names = try testing.allocator.alloc(u32, test_fns.len); - defer testing.allocator.free(names); - const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len); - defer testing.allocator.free(expected_panic_msgs); + const names = try gpa.alloc(u32, test_fns.len); + defer gpa.free(names); + const expected_panic_msgs = try gpa.alloc(u32, test_fns.len); + defer gpa.free(expected_panic_msgs); for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| { name.* = @intCast(string_bytes.items.len); - try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1); + try string_bytes.ensureUnusedCapacity(gpa, test_fn.name.len + 1); string_bytes.appendSliceAssumeCapacity(test_fn.name); string_bytes.appendAssumeCapacity(0); expected_panic_msg.* = 0; diff --git a/lib/compiler_rt/comparef.zig b/lib/compiler_rt/comparef.zig index 7b397ba02f9aca5a534f015726bcb143a456eb63..d230e9a6b42f8ef88114e4d72b838f3f47c01cec 100644 --- a/lib/compiler_rt/comparef.zig +++ b/lib/compiler_rt/comparef.zig @@ -8,7 +8,7 @@ const Unordered = if (builtin.cpu.arch == .avr) i8 else if (builtin.cpu.arch.isAARCH64()) i32 -else if (builtin.target.cTypeBitSize(.long) >= builtin.target.ptrBitWidth()) +else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth()) c_long else c_longlong; diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index c243c8551f4917ef210159743f0d55ba749d1e6a..ebfe6cd502f399501eeafdbdf44205ca6636e8d2 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2817,12 +2817,12 @@ pub const Allocating = struct { } test Allocating { - try testAllocating(.fromByteUnits(1)); - try testAllocating(.fromByteUnits(4)); - try testAllocating(.fromByteUnits(8)); - try testAllocating(.fromByteUnits(16)); - try testAllocating(.fromByteUnits(32)); - try testAllocating(.fromByteUnits(64)); + try testAllocating(.@"1"); + try testAllocating(.@"4"); + try testAllocating(.@"8"); + try testAllocating(.@"16"); + try testAllocating(.@"32"); + try testAllocating(.@"64"); } }; diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 5dc5075bada694841849a65904acdaa60471a23b..3a6cfabb42be0d191520ef33ae7cbbc190e7c644 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3066,9 +3066,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth { /// Default signedness of `char` for the native C compiler for this target /// Note that char signedness is implementation-defined and many compilers provide /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char -pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { +/// Returns `null` if no C ABI is defined for this target. +pub fn cCharSignedness(target: *const Target) ?std.builtin.Signedness { + switch (target.os.tag) { + .opengl => return null, + else => {}, + } if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; - return switch (target.cpu.arch) { .aarch64, .aarch64_be, @@ -3114,7 +3118,8 @@ pub const CType = enum { longdouble, }; -pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 { return switch (c_type) { .char, .short, @@ -3127,18 +3132,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { .ulonglong, .float, .double, - => @divExact(cTypeBitSize(t, c_type), 8), + => @divExact(cTypeBitSize(t, c_type) orelse return null, 8), - .longdouble => switch (cTypeBitSize(t, c_type)) { + .longdouble => switch (cTypeBitSize(t, c_type) orelse return null) { 64 => 8, - 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, .longdouble))), + 80 => @intCast(std.mem.alignForward(usize, 10, cTypeAlignment(t, c_type).?)), 128 => 16, else => unreachable, }, }; } -pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { switch (target.os.tag) { .freestanding, .other, @@ -3459,15 +3465,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { .longlong, .ulonglong, .longdouble => return 64, }, + .opengl => return null, + .ps3, .contiki, .managarm, - .opengl, => @panic("specify the C integer and float type sizes for this OS"), } } -pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { +/// Returns `null` if no C ABI is defined for this target. +pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 { // Overrides for unusual alignments switch (target.cpu.arch) { .avr, @@ -3500,7 +3508,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { // Next-power-of-two-aligned, up to a maximum. return @min( - std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), + std.math.ceilPowerOfTwoAssert(u16, ((cTypeBitSize(target, c_type) orelse return null) + 7) / 8), @as(u16, switch (target.cpu.arch) { .msp430, .x86_16, @@ -3598,6 +3606,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .xcore, => 4, + .x86 => switch (target.os.tag) { + else => 4, + .uefi, .windows => 8, + }, + .arm, .armeb, .hexagon, @@ -3616,7 +3629,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { .sparc, .thumb, .thumbeb, - .x86, .xtensa, .xtensaeb, => 8, diff --git a/lib/std/math/gamma.zig b/lib/std/math/gamma.zig index ce9a2b07f91b2cc5e5909069813d28bd4b7e9ce6..fed7e87ceef250eb92b67d43973289635c54d06c 100644 --- a/lib/std/math/gamma.zig +++ b/lib/std/math/gamma.zig @@ -263,8 +263,6 @@ test gamma { } test "gamma.special" { - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 - inline for (&.{ f32, f64 }) |T| { try expect(std.math.isNan(gamma(T, -std.math.nan(T)))); try expect(std.math.isNan(gamma(T, std.math.nan(T)))); diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 48ae8216b9026099894b01f95ca9505215bef869..a19a54651db7736b3a31ca926c534690ee27bf79 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -5999,7 +5999,7 @@ pub const WipFunction = struct { alignment: Alignment, name: []const u8, ) Allocator.Error!Value { - return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name); + return self.loadAtomic(access_kind, ty, ptr, undefined, .none, alignment, name); } pub fn loadAtomic( @@ -6043,7 +6043,7 @@ pub const WipFunction = struct { ptr: Value, alignment: Alignment, ) Allocator.Error!Instruction.Index { - return self.storeAtomic(kind, val, ptr, .system, .none, alignment); + return self.storeAtomic(kind, val, ptr, undefined, .none, alignment); } pub fn storeAtomic( diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 2315405a9e89549e26a875b00b51390fc3bc1b3d..e30cae2a6728a7df71e9bef14f194f6264809604 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -499,31 +499,12 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 { } pub fn intAlignment(target: *const std.Target, bits: u16) u16 { - return switch (target.cpu.arch) { - .x86 => switch (bits) { - 0...8 => 1, - 9...16 => 2, - 17...32 => 4, - 33...64 => switch (target.os.tag) { - .uefi, .windows => 8, - else => 4, - }, - else => 16, - }, - .x86_64 => switch (bits) { - 0...8 => 1, - 9...16 => 2, - 17...32 => 4, - 33...64 => 8, - else => 16, - }, - else => switch (bits) { - 0 => 1, - else => @min( - std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), - target.cMaxIntAlignment(), - ), - }, + return switch (bits) { + 0 => 1, + else => @min( + std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), + target.cMaxIntAlignment(), + ), }; } @@ -536,7 +517,10 @@ pub fn compilerRtFloatAbi(target: *const std.Target, bits: u16) std.Target.Abi.F 16 => if (target.cpu.arch.isMIPS() or target.cpu.arch.isPowerPC()) return no_c_type_available, 32, 64 => {}, 80 => if (target.cTypeBitSize(.longdouble) != 80) return no_c_type_available, - 128 => if (target.cTypeBitSize(.longdouble) <= 64) return no_c_type_available, + 128 => { + if (target.cpu.arch.isX86()) return .hard; // if (target.abi == .msvc) __m128i else __float128 + if (target.cTypeBitSize(.longdouble) != 128) return no_c_type_available; + }, } return .hard; } diff --git a/src/Sema.zig b/src/Sema.zig index bb2cd4eff32547c659ec0e7f14fddf3cc4b07d18..cb8f87836a5e2c8623670cb870f7bf2b4b05a43d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29657,7 +29657,7 @@ fn coerceVarArgParam( .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), .float => float: { const target = zcu.getTarget(); - const double_bits = target.cTypeBitSize(.double); + const double_bits = target.cTypeBitSize(.double) orelse break :float inst; const inst_bits = uncasted_ty.floatBits(target); if (inst_bits >= double_bits) break :float inst; switch (double_bits) { @@ -29673,21 +29673,21 @@ fn coerceVarArgParam( if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .int, .unsigned => .uint, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }) orelse break :int inst) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_int, .unsigned => .c_uint, }, inst, inst_src); if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .long, .unsigned => .ulong, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_long, .unsigned => .c_ulong, }, inst, inst_src); if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .longlong, .unsigned => .ulonglong, - })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }).?) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_longlong, .unsigned => .c_ulonglong, }, inst, inst_src); diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index ef8e24c86744023e52bef9d9c2d0f1f029936852..b3de4f8433a768a6a5c4c174fb300f1a899edf64 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -364,7 +364,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const a = struct_obj.field_aligns.get(ip)[field_idx]; if (a != .none) break :a a; } - break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); + break :a field_ty.abiAlignment(zcu); }; align_out.* = field_align; if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) { diff --git a/src/Type.zig b/src/Type.zig index 56b2388710b2b919a2a429fd3afa0dfa515bcf66..466a707b998294905c7d068acc1f2c98193232dc 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -957,10 +957,25 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { if (vector_type.len == 0) return .@"1"; switch (zcu.comp.getZigBackend()) { else => { - const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); + const elem_ty: Type = .fromInterned(vector_type.child); + switch (if (elem_ty.isRuntimeFloat()) + std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target)) + else + .hard) { + .hard => {}, + .soft => return elem_ty.abiAlignment(zcu), + } + const elem_bits: u32 = @intCast(elem_ty.bitSize(zcu)); if (elem_bits == 0) return .@"1"; const bytes = ((elem_bits * vector_type.len) + 7) / 8; - return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); + const arch = target.cpu.arch; + return .fromByteUnits(std.math.ceilPowerOfTwoAssert( + u32, + if (arch.isArm() or arch.isAARCH64() or arch == .s390x) + @min(bytes, target.stackAlignment()) + else + bytes, + )); }, .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu), .stage2_x86_64 => { @@ -1018,19 +1033,33 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { .c_ulonglong => cTypeAlign(target, .ulonglong), .c_longdouble => cTypeAlign(target, .longdouble), - .f16 => .@"2", - .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float), - .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) { - 64 => cTypeAlign(target, .double), - else => .@"8", - }, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => cTypeAlign(target, .longdouble), - else => Type.u80.abiAlignment(zcu), - }, - .f128 => switch (target.cTypeBitSize(.longdouble)) { - 128 => cTypeAlign(target, .longdouble), - else => .@"16", + .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16 + .f32 => if (target.cTypeBitSize(.float) == 32) + cTypeAlign(target, .float) // abi: c_float, + else + .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32, + .f64 => if (target.cTypeBitSize(.double) == 64) + cTypeAlign(target, .double) // abi: c_double, + else + .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64, + .f80 => if (target.cTypeBitSize(.longdouble) == 80) + cTypeAlign(target, .longdouble) // abi: c_longdouble, + else + .fromByteUnits(switch (std.zig.target.compilerRtFloatAbi(target, 80)) { + .hard => std.zig.target.intAlignment(target, 80), // repr: u80, + .soft => @max( + std.zig.target.intAlignment(target, 64), // mantissa: u64, + std.zig.target.intAlignment(target, 16), // exponent: u16, + ), + }), + .f128 => if (target.cTypeBitSize(.longdouble) == 128) + cTypeAlign(target, .longdouble) // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { + .hard => if (target.cpu.arch.isX86()) + .@"16" // abi: c___float128, + else + .fromByteUnits(std.zig.target.intAlignment(target, 128)), // repr: u128, + .soft => .fromByteUnits(std.zig.target.intAlignment(target, 64)), // lo: u64, hi: u64, }, .generic_poison => unreachable, @@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .vector_type => |vec| { const elem_ty: Type = .fromInterned(vec.child); const bytes = switch (zcu.comp.getZigBackend()) { - else => @divCeil(vec.len * elem_ty.bitSize(zcu), 8), + else => switch (if (elem_ty.isRuntimeFloat()) + std.zig.target.compilerRtFloatAbi(target, elem_ty.floatBits(target)) + else + .hard) { + .hard => @divCeil(vec.len * elem_ty.bitSize(zcu), 8), + .soft => vec.len * elem_ty.abiSize(zcu), + }, .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu), .stage2_x86_64 => switch (elem_ty.toIntern()) { .bool_type => @divCeil(vec.len, 8), @@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu), .usize, .isize => ptrAbiSize(target), - .c_char => target.cTypeByteSize(.char), - .c_short => target.cTypeByteSize(.short), - .c_ushort => target.cTypeByteSize(.ushort), - .c_int => target.cTypeByteSize(.int), - .c_uint => target.cTypeByteSize(.uint), - .c_long => target.cTypeByteSize(.long), - .c_ulong => target.cTypeByteSize(.ulong), - .c_longlong => target.cTypeByteSize(.longlong), - .c_ulonglong => target.cTypeByteSize(.ulonglong), - .c_longdouble => target.cTypeByteSize(.longdouble), + .c_char => target.cTypeByteSize(.char).?, + .c_short => target.cTypeByteSize(.short).?, + .c_ushort => target.cTypeByteSize(.ushort).?, + .c_int => target.cTypeByteSize(.int).?, + .c_uint => target.cTypeByteSize(.uint).?, + .c_long => target.cTypeByteSize(.long).?, + .c_ulong => target.cTypeByteSize(.ulong).?, + .c_longlong => target.cTypeByteSize(.longlong).?, + .c_ulonglong => target.cTypeByteSize(.ulonglong).?, + .c_longdouble => target.cTypeByteSize(.longdouble).?, - .f16 => 2, - .f32 => 4, - .f64 => 8, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => target.cTypeByteSize(.longdouble), - else => Type.u80.abiSize(zcu), + .f16 => std.zig.target.intByteSize(target, 16), // repr: u16 + .f32 => if (target.cTypeBitSize(.float) == 32) + target.cTypeByteSize(.float).? // abi: c_float, + else + std.zig.target.intByteSize(target, 32), // repr: u32, + .f64 => if (target.cTypeBitSize(.double) == 64) + target.cTypeByteSize(.double).? // abi: c_double, + else + std.zig.target.intByteSize(target, 64), // repr: u64, + .f80 => if (target.cTypeBitSize(.longdouble) == 80) + target.cTypeByteSize(.longdouble).? // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 80)) { + .hard => std.zig.target.intByteSize(target, 80), // repr: u80, + .soft => ty.abiAlignment(zcu).forward( + std.zig.target.intByteSize(target, 64) + // mantissa: u64, + std.zig.target.intByteSize(target, 16), // exponent: u16 + ), + }, + .f128 => if (target.cTypeBitSize(.longdouble) == 128) + target.cTypeByteSize(.longdouble).? // abi: c_longdouble, + else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { + .hard => if (target.cpu.arch.isX86()) + 16 // abi: c___float128, + else + std.zig.target.intByteSize(target, 128), // repr: u128, + .soft => std.zig.target.intByteSize(target, 64) * 2, // lo: u64, hi: u64, }, - .f128 => 16, .anyopaque => unreachable, .generic_poison => unreachable, @@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool { /// Returns true if and only if the type is a fixed-width, signed integer. pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.toIntern()) { - .c_char_type => zcu.getTarget().cCharSignedness() == .signed, + .c_char_type => zcu.getTarget().cCharSignedness().? == .signed, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true, else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .int_type => |int_type| int_type.signedness == .signed, @@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { /// Returns true if and only if the type is a fixed-width, unsigned integer. pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.toIntern()) { - .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned, + .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned, .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true, else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .int_type => |int_type| int_type.signedness == .unsigned, @@ -1776,15 +1830,15 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { }, .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() }, .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() }, - .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) }, - .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) }, - .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) }, - .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) }, - .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) }, - .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) }, - .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) }, - .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) }, - .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) }, + .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? }, + .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? }, + .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? }, + .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? }, + .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? }, + .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? }, + .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? }, + .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? }, + .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? }, else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| return int_type, .struct_type => { @@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 { .f64_type => 64, .f80_type => 80, .f128_type, .comptime_float_type => 128, - .c_longdouble_type => target.cTypeBitSize(.longdouble), + .c_longdouble_type => target.cTypeBitSize(.longdouble).?, else => unreachable, }; @@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool { return ty.zigTypeTag(zcu) == .vector; } -/// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len. -pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 { - if (!ty.isVector(zcu)) return 0; - const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type; - return v.len * Type.fromInterned(v.child).bitSize(zcu); -} - pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool { return switch (ty.zigTypeTag(zcu)) { .array, .vector => true, @@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment }; } -/// Returns the alignment a struct field of type `field_ty` will be given if no alignment is -/// explicitly specified. However, in an `extern struct`, a higher alignment may be available due -/// to the struct's full layout (i.e. a field might coincidentally be more aligned). -/// -/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`. -pub fn defaultStructFieldAlignment( - field_ty: Type, - layout: std.lang.Type.ContainerLayout, - zcu: *const Zcu, -) Alignment { - const overalign_big_int = switch (layout) { - .@"packed" => unreachable, - .auto => zcu.getTarget().ofmt == .c, - .@"extern" => true, - }; - const abi_align = field_ty.abiAlignment(zcu); - assert(abi_align != .none); - // We check for anything over 64 here, because the C backend will lower e.g. u64 to a 128-bit - // integer, which has 16-byte alignment. - if (overalign_big_int and - ((field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits > 64) or - (field_ty.toIntern() == .f80_type and zcu.getTarget().cTypeBitSize(.longdouble) != 80))) - { - return abi_align.maxStrict(if (zcu.getTarget().cpu.arch == .s390x) .@"8" else .@"16"); - } - return abi_align; -} - pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value { const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { @@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator } const actual_field_align = switch (field_align) { .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { - .tuple_type, .union_type => field_ty.abiAlignment(zcu), - .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu), + .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu), .ptr_type => Type.usize.abiAlignment(zcu), else => unreachable, }, @@ -3603,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 { pub const packed_struct_layout_version = 2; fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment { - return Alignment.fromByteUnits(target.cTypeAlignment(c_type)); + return .fromByteUnits(target.cTypeAlignment(c_type).?); } diff --git a/src/Value.zig b/src/Value.zig index dfc124659c3f6d9fb3be15430a5734ff2a3fe194..f6905eb4b55d11df4c1610c9c8e41475cd4fe522 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -611,12 +611,7 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .int => |int| switch (int.storage) { .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0], - inline .u64, .i64 => |x| { - if (T == f80) { - @panic("TODO we can't lower this properly on non-x86 llvm backend yet"); - } - return @floatFromInt(x); - }, + inline .u64, .i64 => |x| @floatFromInt(x), }, .float => |float| switch (float.storage) { inline else => |x| @floatCast(x), diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 73cd6ea1e357e38497633fbcbb5af744f1815e1a..1050b8fb0eb1425205f04b7440640ec55d6cf69a 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -12388,7 +12388,7 @@ pub const CallAbiIterator = struct { .f32 => .single, .f64 => .double, .f128 => .quad, - .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) { + .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) { else => unreachable, 64 => .double, 80 => null, diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index 942e4d0660d79fd8bb0e204714586dd7878b3ebe..863a45e2d4bded294e263edff46787942cbcb31b 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { if (bit_size > 64) return .double_integer; return .integer; }, - .int, .@"enum", .error_set, .float, .bool => return .byval, + .int, .@"enum", .error_set, .bool => return .byval, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64, 128 => .byval, + 80 => .double_integer, + }, .vector => { const bit_size = ty.bitSize(zcu); // TODO is this controlled by a cpu feature? diff --git a/src/codegen/arm/abi.zig b/src/codegen/arm/abi.zig index 14acccbb7963991a3c9c201bcebaeb9218af7ff8..bd767560f1c0ac8fb3d5b8b6eed5956ea8e8253d 100644 --- a/src/codegen/arm/abi.zig +++ b/src/codegen/arm/abi.zig @@ -39,7 +39,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; - if (ty.abiAlignment(zcu).compare(.gt, .@"32")) { + if (ty.abiAlignment(zcu).compare(.gt, .@"4")) { return Class.arrSize(bit_size, 64); } @@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; - if (union_obj.alignment.compareStrict(.gt, .@"32")) { + if (union_obj.alignment.compareStrict(.gt, .@"4")) { return Class.arrSize(bit_size, 64); } @@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { } return Class.arrSize(bit_size, 32); }, - .bool, .float => return .byval, + .bool => return .byval, .int => { - // TODO this is incorrect for _BitInt(128) but implementing - // this correctly makes implementing compiler-rt impossible. - // const bit_size = ty.bitSize(zcu); - // if (bit_size > 64) return .memory; + if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory; return .byval; }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64 => .byval, + 80, 128 => .{ .i64_array = 2 }, + }, .@"enum", .error_set => { const bit_size = ty.bitSize(zcu); if (bit_size > 64) return .memory; diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 8e86c0da93dabcda0bdfec08c406bbe0dab4f04d..41ce79a2f5ef333ad5d319f0fbbdd544d9347409 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -130,28 +130,28 @@ pub const CType = union(enum) { pub fn bits(int: Int, target: *const std.Target) u16 { return switch (int) { // zig fmt: off - .char => target.cTypeBitSize(.char), + .char => target.cTypeBitSize(.char).?, - .@"unsigned short" => target.cTypeBitSize(.ushort), - .@"unsigned int" => target.cTypeBitSize(.uint), - .@"unsigned long" => target.cTypeBitSize(.ulong), - .@"unsigned long long" => target.cTypeBitSize(.ulonglong), + .@"unsigned short" => target.cTypeBitSize(.ushort).?, + .@"unsigned int" => target.cTypeBitSize(.uint).?, + .@"unsigned long" => target.cTypeBitSize(.ulong).?, + .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?, - .@"signed short" => target.cTypeBitSize(.short), - .@"signed int" => target.cTypeBitSize(.int), - .@"signed long" => target.cTypeBitSize(.long), - .@"signed long long" => target.cTypeBitSize(.longlong), + .@"signed short" => target.cTypeBitSize(.short).?, + .@"signed int" => target.cTypeBitSize(.int).?, + .@"signed long" => target.cTypeBitSize(.long).?, + .@"signed long long" => target.cTypeBitSize(.longlong).?, - .uintptr_t, .intptr_t => target.ptrBitWidth(), + .uintptr_t, .intptr_t => target.ptrBitWidth(), - .uint8_t, .int8_t => 8, - .uint16_t, .int16_t => 16, - .uint24_t, .int24_t => 24, - .uint32_t, .int32_t => 32, - .uint48_t, .int48_t => 48, - .uint64_t, .int64_t => 64, - .zig_u128, .zig_i128 => 128, - // zig fmt: on + .uint8_t, .int8_t => 8, + .uint16_t, .int16_t => 16, + .uint24_t, .int24_t => 24, + .uint32_t, .int32_t => 32, + .uint48_t, .int48_t => 48, + .uint64_t, .int64_t => 64, + .zig_u128, .zig_i128 => 128, + // zig fmt: on }; } }; diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index bfa368d3ceee36ac575898019e1b48d19a20d066..d591c09bf16d71b77c4d7b2dc3c4659665dd94a1 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -381,7 +381,7 @@ fn defineTuple( const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, tuple_align)) break false; } else true; @@ -402,15 +402,17 @@ fn defineTuple( if (zig_offset == 0 and overalign) { // This is the first field; specify its alignment to align the tuple. try writeFieldAlign(field_ty, tuple_align, w, zcu); - } else if (zig_offset > c_offset) { - // This field needs to be overaligned compared to what its offset would otherwise be. - const need_align: Alignment = .minStrict( - tuple_align, // don't make the struct more aligned than it should be - .fromLog2Units(@ctz(zig_offset)), - ); - try writeFieldAlign(field_ty, need_align, w, zcu); - c_offset = need_align.forward(c_offset); + } else switch (zig_offset - c_offset) { + 0 => {}, + else => |need_bytes| { + // This field needs to be overaligned compared to what its offset would otherwise be. + const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1); + assert(need_align.compareStrict(.lte, tuple_align)); + try writeFieldAlign(field_ty, need_align, w, zcu); + c_offset = need_align.forward(c_offset); + }, } + assert(c_offset == zig_offset); const field_cty: CType = try .lower(field_ty, deps, arena, zcu); try w.print("{f}f{d}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), @@ -443,7 +445,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); const natural_offset = natural_align.forward(offset); const actual_offset = struct_type.field_offsets.get(ip)[field_index]; if (actual_offset < natural_offset) break :pack true; @@ -464,7 +466,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false; } break :overalign true; @@ -481,7 +483,7 @@ fn defineStruct( while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_align = field_ty.abiAlignment(zcu); const natural_offset = switch (pack) { true => offset, false => natural_align.forward(offset), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6d200cacafc52cc7067eefe18f07c1d1a9580768..221c9423e3a035367c010f0d6225940ab70a8ffb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -573,6 +573,8 @@ pub const Object = struct { val: InternPool.Index, @"addrspace": std.lang.AddressSpace, }, Builder.Variable.Index), + /// Same as `uav_map` but for llvm values not originating from the frontend. + const_map: std.AutoHashMapUnmanaged(Builder.Constant, Builder.Variable.Index), /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. @@ -693,6 +695,7 @@ pub const Object = struct { .zcu = zcu, .nav_map = .empty, .uav_map = .empty, + .const_map = .empty, .enum_tag_name_map = .empty, .named_enum_map = .empty, .type_map = .empty, @@ -703,21 +706,22 @@ pub const Object = struct { return obj; } - pub fn deinit(self: *Object) void { - const gpa = self.gpa; - self.type_pool.deinit(gpa); - self.lazy_abi_aligns.deinit(gpa); - self.debug_enums.deinit(gpa); - self.debug_globals.deinit(gpa); - self.debug_file_map.deinit(gpa); - self.debug_types.deinit(gpa); - self.nav_map.deinit(gpa); - self.uav_map.deinit(gpa); - self.enum_tag_name_map.deinit(gpa); - self.named_enum_map.deinit(gpa); - self.type_map.deinit(gpa); - self.builder.deinit(); - self.* = undefined; + pub fn deinit(o: *Object) void { + const gpa = o.gpa; + o.type_pool.deinit(gpa); + o.lazy_abi_aligns.deinit(gpa); + o.debug_enums.deinit(gpa); + o.debug_globals.deinit(gpa); + o.debug_file_map.deinit(gpa); + o.debug_types.deinit(gpa); + o.nav_map.deinit(gpa); + o.uav_map.deinit(gpa); + o.const_map.deinit(gpa); + o.enum_tag_name_map.deinit(gpa); + o.named_enum_map.deinit(gpa); + o.type_map.deinit(gpa); + o.builder.deinit(); + o.* = undefined; } fn genErrorNameTable(o: *Object) Allocator.Error!void { @@ -741,16 +745,16 @@ pub const Object = struct { for (llvm_errors[1..], error_name_list) |*llvm_error, name| { const name_string = try o.builder.stringNull(name.toSlice(ip)); const name_init = try o.builder.stringConst(name_string); - const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); - try name_variable_index.setInitializer(name_init, &o.builder); - name_variable_index.setMutability(.constant, &o.builder); - name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder); - const global_index = name_variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, &o.builder); - global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); + try name_llvm_variable.setInitializer(name_init, &o.builder); + name_llvm_variable.setMutability(.constant, &o.builder); + name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); + const llvm_global = name_llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ - name_variable_index.toConst(&o.builder), + name_llvm_variable.toConst(&o.builder), try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1), }); } @@ -1199,19 +1203,33 @@ pub const Object = struct { global.dll_storage_class = .default; global.unnamed_addr = .unnamed_addr; } - llvm_function.setAlignment(switch (nav.resolved.?.@"align") { - .none => fn_ty.abiAlignment(zcu).toLlvm(), - else => |a| a.toLlvm(), - }, &o.builder); + llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder); llvm_function.setSection(s: { const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none; break :s try o.builder.string(section); }, &o.builder); - try o.addLlvmFunctionAttributes(pt, func.owner_nav, llvm_function); - var attributes = try llvm_function.ptrConst(&o.builder).attributes.toWip(&o.builder); + var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); + // Function attributes that are independent of analysis results of the function body. + try o.addCommonFnAttributes( + &attributes, + owner_mod, + // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`, + // so for these backends, LLVM will happily emit code that accesses the stack through + // the frame pointer. This is nonsensical since what the `naked` attribute does is + // suppress generation of the prologue and epilogue, and the prologue is where the + // frame pointer normally gets set up. At time of writing, this is the case for at + // least x86 and RISC-V. + owner_mod.omit_frame_pointer or fn_info.cc == .naked, + ); + + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, if (nav.getExtern(ip)) |@"extern"| .{ + .name = nav.name.toSlice(ip), + .lib_name = @"extern".lib_name.toSlice(ip), + } else null, .fromIntern(fn_info, ip)); + const func_analysis = func.analysisUnordered(ip); if (func_analysis.is_noinline) { try attributes.addFnAttr(.@"noinline", &o.builder); @@ -1324,7 +1342,7 @@ pub const Object = struct { const counters_variable = try o.builder.addVariable(anon_name, .void, .default); try o.used.append(gpa, counters_variable.toConst(&o.builder)); counters_variable.ptrConst(&o.builder).global.setLinkage(.private, &o.builder); - counters_variable.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); + counters_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); if (target.ofmt == .macho) { counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder); @@ -1507,10 +1525,6 @@ pub const Object = struct { llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr; } - const llvm_align = switch (resolved.@"align") { - .none => nav_ty.abiAlignment(zcu).toLlvm(), - else => |a| a.toLlvm(), - }; const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: { break :s try o.builder.string(section); } else .none; @@ -1519,13 +1533,20 @@ pub const Object = struct { // can see are extern functions or other comptime function body values (e.g. undefined). Of // these, only extern functions need to be lowered to LLVM functions. if (opt_extern != null and nav_ty.zigTypeTag(zcu) == .@"fn" and nav_ty.fnHasRuntimeBits(zcu)) { + const fn_info = zcu.typeToFunc(nav_ty).?; const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) { .function => |function| function, // re-use existing `Builder.Function` .replaced, .alias, .variable => try llvm_global.toNewFunction(&o.builder), }; - llvm_function.setAlignment(llvm_align, &o.builder); + llvm_function.setAlignment(resolved.@"align".toLlvm(), &o.builder); llvm_function.setSection(llvm_section, &o.builder); - try o.addLlvmFunctionAttributes(pt, nav_id, llvm_function); + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{ + .name = nav.name.toSlice(ip), + .lib_name = opt_extern.?.lib_name.toSlice(ip), + }, .fromIntern(fn_info, ip)); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); } else { const file_scope = nav.srcInst(ip).resolveFile(ip); const mod = zcu.fileByIndex(file_scope).mod.?; @@ -1534,7 +1555,10 @@ pub const Object = struct { .variable => |variable| variable, // re-use existing `Builder.Variable` .replaced, .alias, .function => try llvm_global.toNewVariable(&o.builder), }; - llvm_variable.setAlignment(llvm_align, &o.builder); + llvm_variable.setAlignment(switch (resolved.@"align") { + .none => nav_ty.abiAlignment(zcu).toLlvm(), + else => |a| a.toLlvm(), + }, &o.builder); llvm_variable.setSection(llvm_section, &o.builder); llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder); try llvm_variable.setInitializer(if (opt_extern != null) .no_init else try o.lowerValue(resolved.value, .in_memory), &o.builder); @@ -1585,7 +1609,7 @@ pub const Object = struct { const uav_ty = Value.fromInterned(uav).typeOf(zcu); const uav_ref = try o.lowerUavRef( uav, - uav_ty.abiAlignment(zcu), + uav_ty.abiAlignment(zcu).toLlvm(), target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), ); break :exp .{ uav_ty, uav_ref }; @@ -1599,7 +1623,7 @@ pub const Object = struct { fn updateExportedGlobal( o: *Object, - global_index: Builder.Global.Index, + llvm_global: Builder.Global.Index, ty: Type, export_indices: []const Zcu.Export.Index, ) link.Error!void { @@ -1634,11 +1658,11 @@ pub const Object = struct { // make much sense: the linksection should be associated with the declaration itself rather // than some particular symbol it is exported as! if (export_indices[0].ptr(zcu).opts.section.toSlice(ip)) |section_slice| { - const variable = &global_index.ptrConst(&o.builder).kind.variable; + const variable = &llvm_global.ptrConst(&o.builder).kind.variable; variable.setSection(try o.builder.string(section_slice), &o.builder); } - const llvm_global_ty = global_index.typeOf(&o.builder); + const llvm_global_ty = llvm_global.typeOf(&o.builder); // All exports are represented as aliases to the original global. @@ -1661,8 +1685,8 @@ pub const Object = struct { const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - global_index.ptrConst(&o.builder).addr_space, - global_index.toConst(), + llvm_global.ptrConst(&o.builder).addr_space, + llvm_global.toConst(), ); break :global alias.ptrConst(&o.builder).global; }; @@ -1671,12 +1695,9 @@ pub const Object = struct { switch (existing_global.ptrConst(&o.builder).kind) { .alias => |alias| { // We can just repurpose the existing alias. - alias.setAliasee(global_index.toConst(), &o.builder); - alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder); - // If the type the alias is pointing to can change, then - // it makes sense that we should update the address - // space too. - alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = global_index.ptrConst(&o.builder).addr_space; + alias.setAliasee(llvm_global.toConst(), &o.builder); + alias.ptrConst(&o.builder).global.ptr(&o.builder).type = llvm_global.typeOf(&o.builder); + alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = llvm_global.ptrConst(&o.builder).addr_space; break :global existing_global; }, .variable, .function => { @@ -1686,13 +1707,13 @@ pub const Object = struct { // We need to make a new global which is an alias. Replace this existing one // with the target global, making the name available and fixing references // to this global to point to the target. - try existing_global.replace(global_index, &o.builder); + try existing_global.replace(llvm_global, &o.builder); // The name is now free, so create an alias. const alias = try o.builder.addAlias( exp_name, llvm_global_ty, - global_index.ptrConst(&o.builder).addr_space, - global_index.toConst(), + llvm_global.ptrConst(&o.builder).addr_space, + llvm_global.toConst(), ); break :global alias.ptrConst(&o.builder).global; }, @@ -1725,11 +1746,11 @@ pub const Object = struct { pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { _ = o.type_map.remove(ty); try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); - if (o.named_enum_map.get(ty)) |function_index| { - try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index); + if (o.named_enum_map.get(ty)) |llvm_function| { + try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function); } - if (o.enum_tag_name_map.get(ty)) |function_index| { - try o.updateEnumTagNameFunction(.fromInterned(ty), function_index); + if (o.enum_tag_name_map.get(ty)) |llvm_function| { + try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function); } } @@ -2102,7 +2123,7 @@ pub const Object = struct { payload_offset * 8, ); - return try o.builder.debugStructType( + return o.builder.debugStructType( name, null, // File o.debug_compile_unit.unwrap().?, // Scope @@ -2140,7 +2161,7 @@ pub const Object = struct { defer debug_param_types.deinit(gpa); // Return type goes first. - if (try fnReturnStrat(o, fn_info) == .sret) { + if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) { // Actual return type is void, then first arg is the sret pointer. const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type)); debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void)); @@ -2575,50 +2596,114 @@ pub const Object = struct { fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { const zcu = o.zcu; const namespace = zcu.namespacePtr(namespace_index); - if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); + if (namespace.parent == .none) return o.getDebugFile(namespace.file_scope); return o.getDebugType(pt, .fromInterned(namespace.owner_type)); } - /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the - /// given `Nav` (which is a function). - fn addLlvmFunctionAttributes( + fn addCommonFnAttributes( + o: *Object, + attributes: *Builder.FunctionAttributes.Wip, + owner_mod: *Module, + omit_frame_pointer: bool, + ) Allocator.Error!void { + if (!owner_mod.red_zone) { + try attributes.addFnAttr(.noredzone, &o.builder); + } + if (omit_frame_pointer) { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("frame-pointer"), + .value = try o.builder.string("none"), + } }, &o.builder); + } else { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("frame-pointer"), + .value = try o.builder.string("all"), + } }, &o.builder); + } + try attributes.addFnAttr(.nounwind, &o.builder); + if (owner_mod.unwind_tables != .none) { + try attributes.addFnAttr( + .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, + &o.builder, + ); + } + if (owner_mod.optimize_mode == .small) { + try attributes.addFnAttr(.minsize, &o.builder); + try attributes.addFnAttr(.optsize, &o.builder); + } + const target = &owner_mod.resolved_target.result; + if (target.cpu.model.llvm_name) |s| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("target-cpu"), + .value = try o.builder.string(s), + } }, &o.builder); + } + if (owner_mod.resolved_target.llvm_cpu_features) |s| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("target-features"), + .value = try o.builder.string(std.mem.span(s)), + } }, &o.builder); + } + if (target.abi.float() == .soft) { + // `use-soft-float` means "use software routines for floating point computations". In + // other words, it configures how LLVM lowers basic float instructions like `fcmp`, + // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is + // mostly an orthogonal concept, although obviously we do need hardware float operations + // to actually be able to pass float values in float registers. + // + // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC + // and Clang support for Arm32 and CSKY. We don't currently expose such an option in + // Zig, and using CPU features as the source of truth for this makes for a miserable + // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float + // unless the compiler has explicitly been told otherwise. (And note that our baseline + // CPU models almost all include FPU features!) + // + // Revisit this at some point. + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("use-soft-float"), + .value = try o.builder.string("true"), + } }, &o.builder); + + // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the + // above, this should be revisited if `softfp` support is added. + try attributes.addFnAttr(.noimplicitfloat, &o.builder); + } + } + + pub fn addCallingConventionFnAttributes( o: *Object, pt: Zcu.PerThread, - nav_id: InternPool.Nav.Index, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, + attributes: *Builder.FunctionAttributes.Wip, + opt_extern: ?struct { + name: []const u8, + lib_name: ?[]const u8 = null, + }, + fn_info: FuncInfo, ) Allocator.Error!void { const zcu = o.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_id); - const owner_mod = zcu.navFileScope(nav_id).mod.?; - const ty: Type = .fromInterned(nav.resolved.?.type); - - const fn_info = zcu.typeToFunc(ty).?; - const target = &owner_mod.resolved_target.result; - - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - - if (target.cpu.arch.isWasm()) if (nav.getExtern(ip)) |@"extern"| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("wasm-import-name"), - .value = try o.builder.string(nav.name.toSlice(ip)), - } }, &o.builder); - if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| { - if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("wasm-import-module"), - .value = try o.builder.string(lib_name_slice), - } }, &o.builder); - } - }; + const target = zcu.getTarget(); if (fn_info.cc == .async) { @panic("TODO: LLVM backend lower async function"); } + if (target.cpu.arch.isWasm()) if (opt_extern) |@"extern"| { + try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("wasm-import-name"), + .value = try o.builder.string(@"extern".name), + } }, &o.builder); + if (@"extern".lib_name) |lib_name| { + if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ + .kind = try o.builder.string("wasm-import-module"), + .value = try o.builder.string(lib_name), + } }, &o.builder); + } + }; + const cc_info = toLlvmCallConv(fn_info.cc, target).?; - function_index.setCallConv(cc_info.llvm_cc, &o.builder); + llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); if (cc_info.align_stack) { try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); @@ -2672,29 +2757,16 @@ pub const Object = struct { else => {}, } - // Function attributes that are independent of analysis results of the function body. - try o.addCommonFnAttributes( - &attributes, - owner_mod, - // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`, - // so for these backends, LLVM will happily emit code that accesses the stack through - // the frame pointer. This is nonsensical since what the `naked` attribute does is - // suppress generation of the prologue and epilogue, and the prologue is where the - // frame pointer normally gets set up. At time of writing, this is the case for at - // least x86 and RISC-V. - owner_mod.omit_frame_pointer or fn_info.cc == .naked, - ); - if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); - var it = iterateParamTypes(o, fn_info); - if (try fnReturnStrat(o, fn_info) == .sret) { - // Sret pointers must not be address 0 - try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder); - try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder); - - const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory); - try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); + if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) { + try o.addSRetFnAttributes( + attributes, + try o.lowerType(.fromInterned(fn_info.return_type), .in_memory), + Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(), + .declaration, + ); it.llvm_index += 1; } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) { .signed => try attributes.addRetAttr(.signext, &o.builder), @@ -2713,9 +2785,9 @@ pub const Object = struct { while (try it.next()) |lowering| switch (lowering) { .byval => { const param_index = it.zig_index - 1; - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty: Type = .fromInterned(fn_info.param_types[param_index]); if (!isByRef(param_ty, zcu)) { - try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); + try o.addByValParamAttrs(pt, attributes, param_ty, param_index, fn_info, it.llvm_index - 1); } if (remaining_inreg_int > 0 and @@ -2734,12 +2806,12 @@ pub const Object = struct { } }, .byref => { - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); + const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]); + try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty); }, .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), .slice => { - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_ptr_index = it.llvm_index - 2; if (std.math.cast(u5, it.zig_index - 1)) |i| { @@ -2771,78 +2843,24 @@ pub const Object = struct { .i64_array, => continue, }; - - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); } - fn addCommonFnAttributes( + pub fn addSRetFnAttributes( o: *Object, attributes: *Builder.FunctionAttributes.Wip, - owner_mod: *Module, - omit_frame_pointer: bool, + ret_ty: Builder.Type, + ret_align: Builder.Alignment, + location: enum { declaration, callsite }, ) Allocator.Error!void { - if (!owner_mod.red_zone) { - try attributes.addFnAttr(.noredzone, &o.builder); - } - if (omit_frame_pointer) { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("frame-pointer"), - .value = try o.builder.string("none"), - } }, &o.builder); - } else { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("frame-pointer"), - .value = try o.builder.string("all"), - } }, &o.builder); - } - try attributes.addFnAttr(.nounwind, &o.builder); - if (owner_mod.unwind_tables != .none) { - try attributes.addFnAttr( - .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, - &o.builder, - ); - } - if (owner_mod.optimize_mode == .small) { - try attributes.addFnAttr(.minsize, &o.builder); - try attributes.addFnAttr(.optsize, &o.builder); - } - const target = &owner_mod.resolved_target.result; - if (target.cpu.model.llvm_name) |s| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("target-cpu"), - .value = try o.builder.string(s), - } }, &o.builder); - } - if (owner_mod.resolved_target.llvm_cpu_features) |s| { - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("target-features"), - .value = try o.builder.string(std.mem.span(s)), - } }, &o.builder); - } - if (target.abi.float() == .soft) { - // `use-soft-float` means "use software routines for floating point computations". In - // other words, it configures how LLVM lowers basic float instructions like `fcmp`, - // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is - // mostly an orthogonal concept, although obviously we do need hardware float operations - // to actually be able to pass float values in float registers. - // - // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC - // and Clang support for Arm32 and CSKY. We don't currently expose such an option in - // Zig, and using CPU features as the source of truth for this makes for a miserable - // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float - // unless the compiler has explicitly been told otherwise. (And note that our baseline - // CPU models almost all include FPU features!) - // - // Revisit this at some point. - try attributes.addFnAttr(.{ .string = .{ - .kind = try o.builder.string("use-soft-float"), - .value = try o.builder.string("true"), - } }, &o.builder); - - // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the - // above, this should be revisited if `softfp` support is added. - try attributes.addFnAttr(.noimplicitfloat, &o.builder); - } + try attributes.addParamAttr(0, .dead_on_unwind, &o.builder); + switch (location) { + .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder), + .callsite => {}, + } + try attributes.addParamAttr(0, .writeonly, &o.builder); + try attributes.addParamAttr(0, .{ .captures = .none }, &o.builder); + try attributes.addParamAttr(0, .{ .sret = ret_ty }, &o.builder); + try attributes.addParamAttr(0, .{ .@"align" = .wrap(ret_align) }, &o.builder); } pub const TypeRepr = enum { @@ -2861,6 +2879,151 @@ pub const Object = struct { }); } + pub const SoftF80Layout = struct { + alignment: InternPool.Alignment, + /// byte offset of u64 field + mantissa_offset: u64, + /// byte offset of u16 field + exponent_offset: u64, + llvm_fields_len: u32, + + pub const LlvmFieldTag = enum { mantissa, exponent, padding }; + }; + pub fn softF80Layout(o: *Object, opts: struct { + llvm_field_tags_buf: []SoftF80Layout.LlvmFieldTag = &.{}, + llvm_field_types_buf: []Builder.Type = &.{}, + }) Allocator.Error!SoftF80Layout { + const zcu = o.zcu; + const target = zcu.getTarget(); + assert(std.zig.target.compilerRtFloatAbi(target, 80) == .soft); + // Current compiler rt soft abi, which is not yet affected by endianness for simplicity: + // + // typedef struct { uint64_t mantissa; uint16_t exponent; } f80; + // + var layout: SoftF80Layout = .{ + .alignment = Type.f80.abiAlignment(zcu), + .mantissa_offset = undefined, + .exponent_offset = undefined, + .llvm_fields_len = 0, + }; + var offset: u64 = 0; + for ([2]SoftF80Layout.LlvmFieldTag{ .mantissa, .exponent }, [2]Type{ .u64, .u16 }) |field_tag, field_type| { + const field_align = field_type.abiAlignment(zcu); + assert(field_align.compareStrict(.lte, layout.alignment)); + const field_offset = field_align.forward(offset); + switch (field_offset - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + switch (field_tag) { + .mantissa => layout.mantissa_offset = field_offset, + .exponent => layout.exponent_offset = field_offset, + .padding => unreachable, + } + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); + layout.llvm_fields_len += 1; + offset = field_offset + field_type.abiSize(zcu); + } + const end = layout.alignment.forward(offset); + assert(end == Type.f80.abiSize(zcu)); + switch (end - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + return layout; + } + + pub const SoftF128Layout = struct { + alignment: InternPool.Alignment, + /// byte offset of u64 field + lo_offset: u64, + /// byte offset of u64 field + hi_offset: u64, + llvm_fields_len: u32, + + pub const LlvmFieldTag = enum { lo, hi, padding }; + }; + pub fn softF128Layout(o: *Object, opts: struct { + llvm_field_tags_buf: []SoftF128Layout.LlvmFieldTag = &.{}, + llvm_field_types_buf: []Builder.Type = &.{}, + }) Allocator.Error!SoftF128Layout { + const zcu = o.zcu; + const target = zcu.getTarget(); + assert(std.zig.target.compilerRtFloatAbi(target, 128) == .soft); + // Current compiler rt soft abi: + // + // #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // typedef struct { uint64_t hi, lo; } f128; + // #else + // typedef struct { uint64_t lo, hi; } f128; + // #endif + // + var layout: SoftF128Layout = .{ + .alignment = Type.f128.abiAlignment(zcu), + .lo_offset = undefined, + .hi_offset = undefined, + .llvm_fields_len = 0, + }; + var offset: u64 = 0; + for (@as([2]SoftF128Layout.LlvmFieldTag, switch (target.cpu.arch.endian()) { + .big => .{ .hi, .lo }, + .little => .{ .lo, .hi }, + }), [2]Type{ .u64, .u64 }) |field_tag, field_type| { + const field_align = field_type.abiAlignment(zcu); + assert(field_align.compareStrict(.lte, layout.alignment)); + const field_offset = field_align.forward(offset); + switch (field_offset - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + switch (field_tag) { + .lo => layout.lo_offset = field_offset, + .hi => layout.hi_offset = field_offset, + .padding => unreachable, + } + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); + layout.llvm_fields_len += 1; + offset = field_offset + field_type.abiSize(zcu); + } + const end = layout.alignment.forward(offset); + assert(end == Type.f128.abiSize(zcu)); + switch (end - offset) { + 0 => {}, + else => |padding| { + if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) + opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; + if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) + opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); + layout.llvm_fields_len += 1; + }, + } + return layout; + } + pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type { const zcu = o.zcu; const target = zcu.getTarget(); @@ -2901,7 +3064,7 @@ pub const Object = struct { .c_ulonglong_type, => |tag| try o.builder.intType(target.cTypeBitSize( @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), - )), + ).?), .c_longdouble_type, .f16_type, .f32_type, @@ -2909,11 +3072,44 @@ pub const Object = struct { .f80_type, .f128_type, => switch (t.floatBits(target)) { - 16 => if (backendSupportsF16(target)) .half else .i16, - 32 => .float, - 64 => .double, - 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80, - 128 => .fp128, + 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .half, + .soft => .i16, + }, + 32 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .float, + .soft => .i32, + }, + 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .double, + .soft => .i64, + }, + 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .x86_fp80, + .soft => { + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f80_layout = try o.softF80Layout(.{ + .llvm_field_types_buf = &llvm_field_types_buf, + }); + return o.builder.structType( + .normal, + llvm_field_types_buf[0..f80_layout.llvm_fields_len], + ); + }, + }, + 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => .fp128, + .soft => { + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f128_layout = try o.softF128Layout(.{ + .llvm_field_types_buf = &llvm_field_types_buf, + }); + return o.builder.structType( + .normal, + llvm_field_types_buf[0..f128_layout.llvm_fields_len], + ); + }, + }, else => unreachable, }, .anyopaque_type => { @@ -2992,11 +3188,13 @@ pub const Object = struct { array_type.lenIncludingSentinel(), try o.lowerType(.fromInterned(array_type.child), repr), ), - .vector_type => |vector_type| o.builder.vectorType( - .normal, - vector_type.len, - try o.lowerType(.fromInterned(vector_type.child), .as_value), - ), + .vector_type => |vector_type| if (isByRef(t, zcu)) { + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .in_memory); + return o.builder.arrayType(vector_type.len, child_llvm_ty); + } else { + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value); + return o.builder.vectorType(.normal, vector_type.len, child_llvm_ty); + }, .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. switch (Type.fromInterned(child_ty).classify(zcu)) { @@ -3257,7 +3455,10 @@ pub const Object = struct { }, .opaque_type, .spirv_type => unreachable, // no runtime bits .enum_type => try o.lowerType(t.backingIntType(zcu), repr), - .func_type => |func_type| try o.lowerFnType(t, func_type), + .func_type => |func_type| { + assert(t.fnHasRuntimeBits(zcu)); + return o.lowerFnType(.fromIntern(func_type, ip)); + }, .error_set_type, .inferred_error_set_type => try o.errorIntType(repr), // values, not types .undef, @@ -3283,14 +3484,28 @@ pub const Object = struct { }; } - fn lowerFnType(o: *Object, fn_ty: Type, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + pub const FuncInfo = struct { + cc: std.lang.CallingConvention, + noalias_bits: u32 = 0, + param_types: []const InternPool.Index, + return_type: InternPool.Index = .void_type, + is_var_args: bool = false, + + pub fn fromIntern(fn_info: InternPool.Key.FuncType, ip: *InternPool) FuncInfo { + return .{ + .cc = fn_info.cc, + .noalias_bits = fn_info.noalias_bits, + .param_types = fn_info.param_types.get(ip), + .return_type = fn_info.return_type, + .is_var_args = fn_info.is_var_args, + }; + } + }; + pub fn lowerFnType(o: *Object, fn_info: FuncInfo) Allocator.Error!Builder.Type { const zcu = o.zcu; - const ip = &zcu.intern_pool; const target = zcu.getTarget(); - assert(fn_ty.fnHasRuntimeBits(zcu)); - - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); var llvm_params: std.ArrayList(Builder.Type) = .empty; defer llvm_params.deinit(o.gpa); @@ -3305,24 +3520,24 @@ pub const Object = struct { try llvm_params.append(o.gpa, llvm_ptr_ty); } - var it = iterateParamTypes(o, fn_info); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); while (try it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); }, .abi_sized_int => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.append(o.gpa, try o.builder.intType( @intCast(param_ty.abiSize(zcu) * 8), )); }, .slice => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); try llvm_params.appendSlice(o.gpa, &.{ try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)), try o.lowerType(.usize, .as_value), @@ -3332,7 +3547,7 @@ pub const Object = struct { try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]); }, .float_array => |count| { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory); try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); }, @@ -3460,18 +3675,12 @@ pub const Object = struct { }, .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr), .float => switch (ty.floatBits(target)) { - 16 => if (backendSupportsF16(target)) - try o.builder.halfConst(val.toFloat(f16, zcu)) - else - try o.builder.intConst(.i16, @as(i16, @bitCast(val.toFloat(f16, zcu)))), - 32 => try o.builder.floatConst(val.toFloat(f32, zcu)), - 64 => try o.builder.doubleConst(val.toFloat(f64, zcu)), - 80 => if (backendSupportsF80(target)) - try o.builder.x86_fp80Const(val.toFloat(f80, zcu)) - else - try o.builder.intConst(.i80, @as(i80, @bitCast(val.toFloat(f80, zcu)))), - 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), else => unreachable, + 16 => try o.f16Const(val.toFloat(f16, zcu)), + 32 => try o.f32Const(val.toFloat(f32, zcu)), + 64 => try o.f64Const(val.toFloat(f64, zcu)), + 80 => try o.f80Const(val.toFloat(f80, zcu)), + 128 => try o.f128Const(val.toFloat(f128, zcu)), }, .ptr => try o.lowerPtr(arg_val, 0), .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{ @@ -3590,12 +3799,13 @@ pub const Object = struct { }, .vector_type => |vector_type| { const vector_ty = try o.lowerType(ty, repr); + const ExpectedContents = [Builder.expected_fields_len]Builder.Constant; + var bfa_buf: ExpectedContents = undefined; + var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa); + const allocator = bfa.allocator(); + const is_by_ref = isByRef(ty, zcu); switch (aggregate.storage) { .bytes, .elems => { - const ExpectedContents = [Builder.expected_fields_len]Builder.Constant; - var bfa_buf: ExpectedContents = undefined; - var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), o.gpa); - const allocator = bfa.allocator(); const vals = try allocator.alloc(Builder.Constant, vector_type.len); defer allocator.free(vals); @@ -3604,16 +3814,21 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, .as_value); + result_val.* = try o.lowerValue(elem, if (is_by_ref) .in_memory else .as_value); }, .repeated_elem => unreachable, } - return o.builder.vectorConst(vector_ty, vals); + return if (is_by_ref) + o.builder.arrayConst(vector_ty, vals) + else + o.builder.vectorConst(vector_ty, vals); }, - .repeated_elem => |elem| return o.builder.splatConst( - vector_ty, - try o.lowerValue(elem, .as_value), - ), + .repeated_elem => |elem| if (is_by_ref) { + const vals = try allocator.alloc(Builder.Constant, vector_type.len); + defer allocator.free(vals); + @memset(vals, try o.lowerValue(elem, .in_memory)); + return o.builder.arrayConst(vector_ty, vals); + } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)), } }, .tuple_type => |tuple| { @@ -3841,6 +4056,117 @@ pub const Object = struct { }; } + pub fn f16Const(o: *Object, val: f16) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 16)) { + .hard => o.builder.halfConst(val), + .soft => o.builder.intConst(.i16, @as(u16, @bitCast(val))), + }; + } + + pub fn f32Const(o: *Object, val: f32) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 32)) { + .hard => o.builder.floatConst(val), + .soft => o.builder.intConst(.i32, @as(u32, @bitCast(val))), + }; + } + + pub fn f64Const(o: *Object, val: f64) Allocator.Error!Builder.Constant { + return switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 64)) { + .hard => o.builder.doubleConst(val), + .soft => o.builder.intConst(.i64, @as(u64, @bitCast(val))), + }; + } + + pub fn f80Const(o: *Object, val: f80) Allocator.Error!Builder.Constant { + switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 80)) { + .hard => return o.builder.x86_fp80Const(val), + .soft => {}, + } + var llvm_field_tags_buf: [5]SoftF80Layout.LlvmFieldTag = undefined; + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f80_layout = try o.softF80Layout(.{ + .llvm_field_tags_buf = &llvm_field_tags_buf, + .llvm_field_types_buf = &llvm_field_types_buf, + }); + const llvm_field_types = llvm_field_types_buf[0..f80_layout.llvm_fields_len]; + const f80_llvm_ty = try o.builder.structType(.normal, llvm_field_types); + const f80_repr: packed struct { mantissa: u64, exponent: u16 } = @bitCast(val); + var llvm_field_vals_buf: [5]Builder.Constant = undefined; + const llvm_field_vals = llvm_field_vals_buf[0..f80_layout.llvm_fields_len]; + for ( + llvm_field_vals, + llvm_field_tags_buf[0..f80_layout.llvm_fields_len], + llvm_field_types, + ) |*llvm_field_val, llvm_field_tag, llvm_field_type| + llvm_field_val.* = switch (llvm_field_tag) { + .mantissa => try o.builder.intConst(llvm_field_type, f80_repr.mantissa), + .exponent => try o.builder.intConst(llvm_field_type, f80_repr.exponent), + .padding => try o.builder.undefConst(llvm_field_type), + }; + return o.builder.structConst(f80_llvm_ty, llvm_field_vals); + } + + pub fn f128Const(o: *Object, val: f128) Allocator.Error!Builder.Constant { + switch (std.zig.target.compilerRtFloatAbi(o.zcu.getTarget(), 128)) { + .hard => return o.builder.fp128Const(val), + .soft => {}, + } + var llvm_field_tags_buf: [5]SoftF128Layout.LlvmFieldTag = undefined; + var llvm_field_types_buf: [5]Builder.Type = undefined; + const f128_layout = try o.softF128Layout(.{ + .llvm_field_tags_buf = &llvm_field_tags_buf, + .llvm_field_types_buf = &llvm_field_types_buf, + }); + const llvm_field_types = llvm_field_types_buf[0..f128_layout.llvm_fields_len]; + const f128_llvm_ty = try o.builder.structType(.normal, llvm_field_types); + const f128_repr: packed struct { lo: u64, hi: u64 } = @bitCast(val); + var llvm_field_vals_buf: [5]Builder.Constant = undefined; + const llvm_field_vals = llvm_field_vals_buf[0..f128_layout.llvm_fields_len]; + for ( + llvm_field_vals, + llvm_field_tags_buf[0..f128_layout.llvm_fields_len], + llvm_field_types, + ) |*llvm_field_val, llvm_field_tag, llvm_field_type| + llvm_field_val.* = switch (llvm_field_tag) { + .lo => try o.builder.intConst(llvm_field_type, f128_repr.lo), + .hi => try o.builder.intConst(llvm_field_type, f128_repr.hi), + .padding => try o.builder.undefConst(llvm_field_type), + }; + return o.builder.structConst(f128_llvm_ty, llvm_field_vals); + } + + pub fn lowerConstRef( + o: *Object, + constant: Builder.Constant, + @"align": Builder.Alignment, + ) Allocator.Error!Builder.Constant { + assert(@"align" != .default); + const zcu = o.zcu; + const gpa = zcu.comp.gpa; + const gop = try o.const_map.getOrPut(gpa, constant); + if (gop.found_existing) { + // Keep the greater of the two alignments. + const llvm_variable = gop.value_ptr.*; + const llvm_old_align = llvm_variable.getAlignment(&o.builder); + const llvm_new_align = llvm_old_align.max(@"align"); + llvm_variable.setAlignment(llvm_new_align, &o.builder); + return llvm_variable.ptrConst(&o.builder).global.toConst(); + } + errdefer assert(o.const_map.remove(constant)); + + const llvm_ty = constant.typeOf(&o.builder); + const llvm_addrspace = toLlvmAddressSpace(.generic, zcu.getTarget()); + const llvm_variable = try o.builder.addVariable(.empty, llvm_ty, llvm_addrspace); + gop.value_ptr.* = llvm_variable; + try llvm_variable.setInitializer(constant, &o.builder); + llvm_variable.setMutability(.constant, &o.builder); + llvm_variable.setAlignment(@"align", &o.builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); + return llvm_global.toConst(); + } + fn lowerPtr( o: *Object, ptr_val: InternPool.Index, @@ -3860,7 +4186,7 @@ pub const Object = struct { const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); const base_ptr = try o.lowerUavRef( uav.val, - orig_ptr_ty.ptrAlignment(zcu), + orig_ptr_ty.ptrAlignment(zcu).toLlvm(), orig_ptr_ty.ptrAddressSpace(zcu), ); return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ @@ -3912,8 +4238,8 @@ pub const Object = struct { pub fn lowerPtrToVoid( o: *Object, - /// Must not be `.none`. - @"align": InternPool.Alignment, + /// Must not be `.default`. + @"align": Builder.Alignment, @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { const addr: u64 = @"align".toByteUnits().?; @@ -3926,11 +4252,11 @@ pub const Object = struct { pub fn lowerUavRef( o: *Object, uav_val: InternPool.Index, - /// Must not be `.none`. - @"align": InternPool.Alignment, + /// Must not be `.default`. + @"align": Builder.Alignment, @"addrspace": std.lang.AddressSpace, ) Allocator.Error!Builder.Constant { - assert(@"align" != .none); + assert(@"align" != .default); const zcu = o.zcu; const ip = &zcu.intern_pool; @@ -3955,7 +4281,7 @@ pub const Object = struct { // Keep the greater of the two alignments. const llvm_variable = gop.value_ptr.*; const llvm_old_align = llvm_variable.getAlignment(&o.builder); - const llvm_new_align = llvm_old_align.max(@"align".toLlvm()); + const llvm_new_align = llvm_old_align.max(@"align"); llvm_variable.setAlignment(llvm_new_align, &o.builder); return llvm_variable.ptrConst(&o.builder).global.toConst(); } @@ -3967,7 +4293,7 @@ pub const Object = struct { gop.value_ptr.* = llvm_variable; try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder); llvm_variable.setMutability(.constant, &o.builder); - llvm_variable.setAlignment(@"align".toLlvm(), &o.builder); + llvm_variable.setAlignment(@"align", &o.builder); const llvm_global = llvm_variable.ptrConst(&o.builder).global; llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); @@ -3986,7 +4312,7 @@ pub const Object = struct { .none => nav_ty.abiAlignment(zcu), else => |a| a, }; - return o.lowerPtrToVoid(nav_align, nav.resolved.?.@"addrspace"); + return o.lowerPtrToVoid(nav_align.toLlvm(), nav.resolved.?.@"addrspace"); } const gop = try o.nav_map.getOrPut(gpa, nav_id); @@ -4015,7 +4341,7 @@ pub const Object = struct { attributes: *Builder.FunctionAttributes.Wip, param_ty: Type, param_index: u32, - fn_info: InternPool.Key.FuncType, + fn_info: FuncInfo, llvm_arg_i: u32, ) Allocator.Error!void { const zcu = o.zcu; @@ -4075,18 +4401,18 @@ pub const Object = struct { const name = try o.builder.strtabString("__zig_error_name_table"); // TODO: Address space - const variable_index = try o.builder.addVariable(name, .ptr, .default); - variable_index.setMutability(.constant, &o.builder); - variable_index.setAlignment( + const llvm_variable = try o.builder.addVariable(name, .ptr, .default); + llvm_variable.setMutability(.constant, &o.builder); + llvm_variable.setAlignment( Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(), &o.builder, ); - const global_index = variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, &o.builder); - global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, &o.builder); + llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); - o.error_name_table = variable_index; - return variable_index; + o.error_name_table = llvm_variable; + return llvm_variable; } pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index { @@ -4094,13 +4420,13 @@ pub const Object = struct { if (o.errors_len_variable == .none) { const llvm_err_int_ty = try o.errorIntType(.in_memory); const name = try builder.strtabString("__zig_errors_len"); - const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default); - variable_index.setMutability(.constant, builder); - variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); - const global_index = variable_index.ptrConst(&o.builder).global; - global_index.setLinkage(.private, builder); - global_index.setUnnamedAddr(.unnamed_addr, builder); - o.errors_len_variable = variable_index; + const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default); + llvm_variable.setMutability(.constant, builder); + llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); + const llvm_global = llvm_variable.ptrConst(&o.builder).global; + llvm_global.setLinkage(.private, builder); + llvm_global.setUnnamedAddr(.unnamed_addr, builder); + o.errors_len_variable = llvm_variable; } return o.errors_len_variable; } @@ -4112,21 +4438,21 @@ pub const Object = struct { const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern()); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern())); - const function_index = try o.builder.addFunction( + const llvm_function = try o.builder.addFunction( // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. // TODO: change the builder API so we don't need to do this. try o.builder.fnType(.void, &.{}, .normal), try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), toLlvmAddressSpace(.generic, zcu.getTarget()), ); - gop.value_ptr.* = function_index; - try o.updateEnumTagNameFunction(enum_ty, function_index); - return function_index; + gop.value_ptr.* = llvm_function; + try o.updateEnumTagNameFunction(enum_ty, llvm_function); + return llvm_function; } fn updateEnumTagNameFunction( o: *Object, enum_ty: Type, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, ) Allocator.Error!void { const zcu = o.zcu; const ip = &zcu.intern_pool; @@ -4136,19 +4462,19 @@ pub const Object = struct { const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value); const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); - function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); - function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); + llvm_function.setCallConv(.fastcc, &o.builder); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); var wip = try Builder.WipFunction.init(&o.builder, .{ - .function = function_index, + .function = llvm_function, .strip = true, }); defer wip.deinit(); @@ -4167,16 +4493,16 @@ pub const Object = struct { for (0..loaded_enum.field_names.len) |field_index| { const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); const name_init = try o.builder.stringConst(name); - const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); - try name_variable_index.setInitializer(name_init, &o.builder); - name_variable_index.setMutability(.constant, &o.builder); - name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); - const name_global_index = name_variable_index.ptrConst(&o.builder).global; - name_global_index.setLinkage(.private, &o.builder); - name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder); + const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); + try name_llvm_variable.setInitializer(name_init, &o.builder); + name_llvm_variable.setMutability(.constant, &o.builder); + name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); + const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global; + name_llvm_global.setLinkage(.private, &o.builder); + name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); const name_val = try o.builder.structValue(llvm_ret_ty, &.{ - name_global_index.toConst(), + name_llvm_global.toConst(), try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1), }); @@ -4209,40 +4535,40 @@ pub const Object = struct { const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); - const function_index = try o.builder.addFunction( + const llvm_function = try o.builder.addFunction( // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. // TODO: change the builder API so we don't need to do this. try o.builder.fnType(.void, &.{}, .normal), try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), toLlvmAddressSpace(.generic, zcu.getTarget()), ); - gop.value_ptr.* = function_index; - try o.updateIsNamedEnumValueFunction(enum_ty, function_index); - return function_index; + gop.value_ptr.* = llvm_function; + try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function); + return llvm_function; } fn updateIsNamedEnumValueFunction( o: *Object, enum_ty: Type, - function_index: Builder.Function.Index, + llvm_function: Builder.Function.Index, ) Allocator.Error!void { const zcu = o.zcu; const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); - function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); - function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); + llvm_function.setCallConv(.fastcc, &o.builder); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); var wip: Builder.WipFunction = try .init(&o.builder, .{ - .function = function_index, + .function = llvm_function, .strip = true, }); defer wip.deinit(); @@ -4278,20 +4604,27 @@ pub const Object = struct { pub fn getLibcFunction( o: *Object, + pt: Zcu.PerThread, fn_name: Builder.StrtabString, - param_types: []const Builder.Type, - return_type: Builder.Type, + fn_info: FuncInfo, ) Allocator.Error!Builder.Function.Index { if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, .function => |function| function, .variable, .replaced => unreachable, }; - return o.builder.addFunction( - try o.builder.fnType(return_type, param_types, .normal), + const llvm_function = try o.builder.addFunction( + try o.lowerFnType(fn_info), fn_name, toLlvmAddressSpace(.generic, o.zcu.getTarget()), ); + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCallingConventionFnAttributes(pt, llvm_function, &attributes, .{ + .name = fn_name.slice(&o.builder).?, + }, fn_info); + llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); + return llvm_function; } }; @@ -4585,47 +4918,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target: }; } -/// This function returns true if we expect LLVM to lower f16 correctly -/// and false if we expect LLVM to crash if it encounters an f16 type, -/// or if it produces miscompilations. -pub fn backendSupportsF16(target: *const std.Target) bool { - return switch (target.cpu.arch) { - .arm, - .armeb, - .thumb, - .thumbeb, - => target.abi.float() == .soft or target.cpu.has(.arm, .fullfp16), - else => true, - }; -} - -/// This function returns true if we expect LLVM to lower x86_fp80 correctly -/// and false if we expect LLVM to crash if it encounters an x86_fp80 type, -/// or if it produces miscompilations. -pub fn backendSupportsF80(target: *const std.Target) bool { - return switch (target.cpu.arch) { - .x86, .x86_64 => !target.cpu.has(.x86, .soft_float), - else => false, - }; -} - -/// This function returns true if we expect LLVM to lower f128 correctly, -/// and false if we expect LLVM to crash if it encounters an f128 type, -/// or if it produces miscompilations. -pub fn backendSupportsF128(target: *const std.Target) bool { - return switch (target.cpu.arch) { - // https://github.com/llvm/llvm-project/issues/121122 - .amdgcn, - => false, - .arm, - .armeb, - .thumb, - .thumbeb, - => target.abi.float() == .soft or target.cpu.has(.arm, .fp_armv8), - else => true, - }; -} - /// We need to insert extra padding if LLVM's isn't enough. /// However we don't want to ever call LLVMABIAlignmentOfType or /// LLVMABISizeOfType because these functions will trip assertions diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 156aa875926d6d3d55341b2eac6d1e8f93e18972..5bdf5029d1b4a639c41652f0792d56aba08e927a 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -169,7 +169,7 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { // We need a pointer to a global constant, i.e. a UAV. return o.lowerUavRef( val.toIntern(), - ty.abiAlignment(zcu), + ty.abiAlignment(zcu).toLlvm(), target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), ); } @@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { const fn_info = zcu.typeToFunc(fn_ty).?; const param_types = fn_info.param_types.get(ip); - var it = iterateParamTypes(o, fn_info); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types.get(ip)); // Populate `fg.ret_ptr`... - fg.ret_ptr = switch (try fnReturnStrat(o, fn_info)) { + fg.ret_ptr = switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) { .sret => rp: { defer it.llvm_index += 1; break :rp fg.wip.arg(it.llvm_index); @@ -721,29 +721,19 @@ fn genBodyDebugScope( try self.genBody(body, coverage_point); } -const CallAttr = enum { - Auto, - NeverTail, - NeverInline, - AlwaysTail, - AlwaysInline, -}; - -fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value { - const air_call = self.air.unwrapCall(inst); +fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value { + const o = fg.object; + const zcu = o.zcu; + const air_call = fg.air.unwrapCall(inst); const args = air_call.args; - const o = self.object; - const pt = self.pt; - const zcu = o.zcu; const ip = &zcu.intern_pool; - const callee_ty = self.typeOf(air_call.callee); + const callee_ty = fg.typeOf(air_call.callee); const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { .@"fn" => callee_ty, .pointer => callee_ty.childType(zcu), else => unreachable, }; const fn_info = zcu.typeToFunc(zig_fn_ty).?; - const return_type: Type = .fromInterned(fn_info.return_type); const llvm_fn = llvm_fn: { // If the callee is a function *body*, we need to use a pointer to the global. if (air_call.callee.toInterned()) |ip_index| switch (ip.indexToKey(ip_index)) { @@ -752,22 +742,54 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier else => {}, }; // Otherwise, the operand is already a function pointer (possibly runtime-known). - break :llvm_fn try self.resolveInst(air_call.callee); + break :llvm_fn try fg.resolveInst(air_call.callee); }; + + const arg_types = try fg.gpa.alloc(InternPool.Index, args.len); + defer fg.gpa.free(arg_types); + const arg_values = try fg.gpa.alloc(Builder.Value, args.len); + defer fg.gpa.free(arg_values); + for (arg_types, arg_values, args) |*arg_type, *arg_value, arg| { + const arg_ty = fg.typeOf(arg); + arg_type.* = arg_ty.toIntern(); + arg_value.* = if (arg_ty.hasRuntimeBits(zcu)) try fg.resolveInst(arg) else .none; + } + return fg.buildCall(.{ + .is_unused = fg.liveness.isUnused(inst), + .modifier = modifier, + }, try o.lowerType(zig_fn_ty, .as_value), llvm_fn, .fromIntern(fn_info, ip), arg_types, arg_values); +} + +fn buildCall( + fg: *FuncGen, + opts: struct { + is_unused: bool = false, + modifier: std.lang.CallModifier = .auto, + }, + llvm_fn_ty: Builder.Type, + llvm_fn: Builder.Value, + fn_info: Object.FuncInfo, + arg_types: []const InternPool.Index, + arg_values: []const Builder.Value, +) Allocator.Error!Builder.Value { + const o = fg.object; + const pt = fg.pt; + const zcu = o.zcu; + const return_type: Type = .fromInterned(fn_info.return_type); const target = zcu.getTarget(); - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); - var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa); - defer llvm_args.deinit(); + var llvm_args: std.ArrayList(Builder.Value) = .empty; + defer llvm_args.deinit(fg.gpa); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - if (self.disable_intrinsics) { + if (fg.disable_intrinsics) { try attributes.addFnAttr(.nobuiltin, &o.builder); } - switch (modifier) { + switch (opts.modifier) { .auto, .always_tail => {}, .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder), .no_suspend, .always_inline, .compile_time => unreachable, @@ -775,10 +797,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier const sret_alloc: ?Builder.Value = switch (ret_strat) { .sret => sret_alloc: { - try attributes.addParamAttr(0, .{ .sret = try o.lowerType(return_type, .in_memory) }, &o.builder); + const alignment = return_type.abiAlignment(zcu).toLlvm(); + try o.addSRetFnAttributes(&attributes, try o.lowerType(return_type, .in_memory), alignment, .callsite); - const ptr = try self.buildZigAlloca(return_type, .none); - try llvm_args.append(ptr); + const ptr = try fg.buildZigAlloca(return_type, .none); + try llvm_args.append(fg.gpa, ptr); break :sret_alloc ptr; }, else => sret_alloc: { @@ -792,132 +815,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing; if (err_return_tracing) { - assert(self.err_ret_trace != .none); - try llvm_args.append(self.err_ret_trace); + assert(fg.err_ret_trace != .none); + try llvm_args.append(fg.gpa, fg.err_ret_trace); } - var it = iterateParamTypes(o, fn_info); - while (try it.nextCall(self, args)) |lowering| switch (lowering) { - .no_bits => continue, - .byval => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - if (isByRef(param_ty, zcu)) { - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - // We don't need to handle non-ABI-sized integer types in memory here since they are - // never by-ref. - const llvm_param_ty = try o.lowerType(param_ty, .in_memory); - const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); - try llvm_args.append(loaded); - } else { - try llvm_args.append(llvm_arg); - } - }, - .byref => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - if (isByRef(param_ty, zcu)) { - try llvm_args.append(llvm_arg); - } else { - const arg_ptr = try self.buildZigAlloca(param_ty, .none); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); - try llvm_args.append(arg_ptr); - } - }, - .byref_mut => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); + var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); + while (try it.nextCall(arg_types)) |lowering| { + const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]); + const arg_val = arg_values[it.zig_index - 1]; + switch (lowering) { + .no_bits => continue, + .byval => { + if (isByRef(arg_ty, zcu)) { + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + // We don't need to handle non-ABI-sized integer types in memory here since they are + // never by-ref. + const llvm_arg_ty = try o.lowerType(arg_ty, .in_memory); + const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } else { + try llvm_args.append(fg.gpa, arg_val); + } + }, + .byref => { + if (isByRef(arg_ty, zcu)) { + try llvm_args.append(fg.gpa, arg_val); + } else { + const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); + try llvm_args.append(fg.gpa, arg_ptr); + } + }, + .byref_mut => { + const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); + try llvm_args.append(fg.gpa, arg_ptr); + }, + .abi_sized_int => { + const int_llvm_ty = try o.builder.intType(@intCast(arg_ty.abiSize(zcu) * 8)); - const arg_ptr = try self.buildZigAlloca(param_ty, .none); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); - try llvm_args.append(arg_ptr); - }, - .abi_sized_int => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(zcu) * 8)); + if (isByRef(arg_ty, zcu)) { + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } else { + // LLVM does not allow bitcasting structs so we must allocate + // a local, store as one type, and then load as another type. + const alignment = arg_ty.abiAlignment(zcu).toLlvm(); + const ptr = try fg.buildAlloca(int_llvm_ty, alignment); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + const loaded = try fg.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); + try llvm_args.append(fg.gpa, loaded); + } + }, + .slice => { + const ptr = try fg.wip.extractValue(arg_val, &.{0}, ""); + const len = try fg.wip.extractValue(arg_val, &.{1}, ""); + try llvm_args.appendSlice(fg.gpa, &.{ ptr, len }); + }, + .multiple_llvm_types => { + const arg_alignment = arg_ty.abiAlignment(zcu); + const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); + const arg_ptr = try fg.buildAlloca(llvm_ty, arg_alignment.toLlvm()); + try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); - if (isByRef(param_ty, zcu)) { - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, ""); - try llvm_args.append(loaded); - } else { - // LLVM does not allow bitcasting structs so we must allocate - // a local, store as one type, and then load as another type. - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const ptr = try self.buildAlloca(int_llvm_ty, alignment); - try self.store(ptr, .none, llvm_arg, param_ty, .normal); - const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); - try llvm_args.append(loaded); - } - }, - .slice => { - const arg = args[it.zig_index - 1]; - const llvm_arg = try self.resolveInst(arg); - const ptr = try self.wip.extractValue(llvm_arg, &.{0}, ""); - const len = try self.wip.extractValue(llvm_arg, &.{1}, ""); - try llvm_args.appendSlice(&.{ ptr, len }); - }, - .multiple_llvm_types => { - const arg = args[it.zig_index - 1]; - const param_ty = self.typeOf(arg); - const llvm_arg = try self.resolveInst(arg); - const param_alignment = param_ty.abiAlignment(zcu); - const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); - const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm()); - try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); + try llvm_args.ensureUnusedCapacity(fg.gpa, it.types_len); + for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { + const field_ptr = try fg.ptraddConst(arg_ptr, offset); + const loaded = try fg.wip.load(.normal, field_ty, field_ptr, arg_alignment.offset(offset).toLlvm(), ""); + llvm_args.appendAssumeCapacity(loaded); + } + }, + .float_array => |count| { + const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { + const ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + break :ptr ptr; + } else arg_val; - try llvm_args.ensureUnusedCapacity(it.types_len); - for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { - const field_ptr = try self.ptraddConst(arg_ptr, offset); - const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), ""); - llvm_args.appendAssumeCapacity(loaded); - } - }, - .float_array => |count| { - const arg = args[it.zig_index - 1]; - const arg_ty = self.typeOf(arg); - const arg_val = try self.resolveInst(arg); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); + const array_ty = try o.builder.arrayType(count, float_ty); - const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { - const ptr = try self.buildZigAlloca(arg_ty, .none); - try self.store(ptr, .none, arg_val, arg_ty, .normal); - break :ptr ptr; - } else arg_val; + const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); + try llvm_args.append(fg.gpa, loaded); + }, + .i32_array, .i64_array => |arr_len| { + const elem_size: u8 = if (lowering == .i32_array) 32 else 64; - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); - const array_ty = try o.builder.arrayType(count, float_ty); + const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { + const ptr = try fg.buildZigAlloca(arg_ty, .none); + try fg.store(ptr, .none, arg_val, arg_ty, .normal); + break :ptr ptr; + } else arg_val; - const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); - try llvm_args.append(loaded); - }, - .i32_array, .i64_array => |arr_len| { - const elem_size: u8 = if (lowering == .i32_array) 32 else 64; - const arg = args[it.zig_index - 1]; - const arg_ty = self.typeOf(arg); - const arg_val = try self.resolveInst(arg); - - const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { - const ptr = try self.buildZigAlloca(arg_ty, .none); - try self.store(ptr, .none, arg_val, arg_ty, .normal); - break :ptr ptr; - } else arg_val; - - const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); - const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); - try llvm_args.append(loaded); - }, - }; + const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); + const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); + try llvm_args.append(fg.gpa, loaded); + }, + } + } const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?; { // Add argument attributes. - it = iterateParamTypes(o, fn_info); + it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); it.llvm_index += @intFromBool(ret_strat == .sret); it.llvm_index += @intFromBool(err_return_tracing); var remaining_inreg_int = cc_info.inreg_int_params; @@ -925,7 +927,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier while (try it.next()) |lowering| switch (lowering) { .byval => { const param_index = it.zig_index - 1; - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty = Type.fromInterned(fn_info.param_types[param_index]); if (!isByRef(param_ty, zcu)) { try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); } @@ -947,7 +949,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, .byref => { const param_index = it.zig_index - 1; - const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[param_index]); + const param_ty: Type = .fromInterned(fn_info.param_types[param_index]); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); }, .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), @@ -962,7 +964,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier .slice => { assert(!it.byval_attr); - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_arg_i = it.llvm_index - 2; @@ -989,8 +991,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }; } - const call = try self.wip.call( - switch (modifier) { + const call = try fg.wip.call( + switch (opts.modifier) { .auto, .never_inline => .normal, .never_tail => .notail, .always_tail => .musttail, @@ -998,19 +1000,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier }, cc_info.llvm_cc, try attributes.finish(&o.builder), - try o.lowerType(zig_fn_ty, .as_value), + llvm_fn_ty, llvm_fn, llvm_args.items, "", ); - if (fn_info.return_type == .noreturn_type and modifier != .always_tail) { - return .none; - } - - if (self.liveness.isUnused(inst)) { - return .none; - } + if (opts.is_unused) return .none; + if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none; // We exit this `switch` if we have a pointer to the return value. const ret_val_ptr: Builder.Value = switch (ret_strat) { @@ -1020,15 +1017,15 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier .sret => sret_alloc.?, .mem_cast => |llvm_ret_ty| ret_val_ptr: { const alignment = return_type.abiAlignment(zcu).toLlvm(); - const ptr = try self.buildAlloca(llvm_ret_ty, alignment); - _ = try self.wip.store(.normal, call, ptr, alignment); + const ptr = try fg.buildAlloca(llvm_ret_ty, alignment); + _ = try fg.wip.store(.normal, call, ptr, alignment); break :ret_val_ptr ptr; }, }; if (isByRef(return_type, zcu)) { return ret_val_ptr; } else { - return self.load(ret_val_ptr, .none, return_type, .normal); + return fg.load(ret_val_ptr, .none, return_type, .normal); } } @@ -1067,7 +1064,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; - const ret_strat = try fnReturnStrat(o, fn_info); + const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; const ret_ty_align = ret_ty.abiAlignment(zcu); @@ -1141,7 +1138,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const ret_ty = ptr_ty.childType(zcu); const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; const ptr = try self.resolveInst(un_op); - switch (try fnReturnStrat(o, fn_info)) { + switch (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type))) { .void => _ = try self.wip.retVoid(), .sret => { assert(self.ret_ptr != .none); @@ -2028,135 +2025,95 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } -fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { - const o = self.object; +fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { + const o = fg.object; const zcu = o.zcu; - const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try self.resolveInst(ty_op.operand); - const operand_ty = self.typeOf(ty_op.operand); + const operand = try fg.resolveInst(ty_op.operand); + const operand_ty = fg.typeOf(ty_op.operand); const operand_scalar_ty = operand_ty.scalarType(zcu); - const is_signed_int = operand_scalar_ty.isSignedInt(zcu); + const operand_scalar_info = operand_scalar_ty.intInfo(zcu); - const dest_ty = self.typeOfIndex(inst); + const dest_ty = fg.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( - if (is_signed_int) .signed else .unsigned, - operand, - dest_llvm_ty, - "", - ); + if (intrinsicsAllowed(dest_scalar_ty, target)) + return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), ""); - const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse { - return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)}); + const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse { + return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits}); }; - const rt_int_ty = try o.builder.intType(rt_int_bits); - var extended = try self.wip.conv( - if (is_signed_int) .signed else .unsigned, + const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null; + const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value); + const extended = try fg.wip.conv( + .fromStdLang(operand_scalar_info.signedness), operand, - rt_int_ty, + if (vector_len) |len| + try o.builder.vectorType(.normal, len, rt_llvm_int_ty) + else + rt_llvm_int_ty, "", ); - const dest_bits = dest_scalar_ty.floatBits(target); - const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); - const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); - const sign_prefix = if (is_signed_int) "" else "un"; const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{ - sign_prefix, - compiler_rt_operand_abbrev, - compiler_rt_dest_abbrev, + switch (operand_scalar_info.signedness) { + .signed => "", + .unsigned => "un", + }, + compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), + compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)), }); - - var param_type = rt_int_ty; - if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { - // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard - // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. - param_type = try o.builder.vectorType(.normal, 2, .i64); - extended = try self.wip.cast(.bitcast, extended, param_type, ""); - } - - const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{extended}, - "", - ); + return fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{rt_int_ty.toIntern()}, + .return_type = dest_scalar_ty.toIntern(), + }, &.{extended}, vector_len); } fn airIntFromFloat( - self: *FuncGen, + fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind, ) TodoError!Builder.Value { _ = fast; - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); - const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try self.resolveInst(ty_op.operand); - const operand_ty = self.typeOf(ty_op.operand); + const operand = try fg.resolveInst(ty_op.operand); + const operand_ty = fg.typeOf(ty_op.operand); const operand_scalar_ty = operand_ty.scalarType(zcu); - const dest_ty = self.typeOfIndex(inst); + const dest_ty = fg.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); + const dest_scalar_info = dest_scalar_ty.intInfo(zcu); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag - return self.wip.conv( - if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned, - operand, - dest_llvm_ty, - "", - ); + return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, ""); } - const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse { - return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)}); + const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse { + return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits}); }; - const ret_ty = try o.builder.intType(rt_int_bits); - const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { - // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard - // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. - break :b try o.builder.vectorType(.normal, 2, .i64); - } else ret_ty; - - const operand_bits = operand_scalar_ty.floatBits(target); - const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); - - const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); - const sign_prefix = if (dest_scalar_ty.isSignedInt(zcu)) "" else "uns"; - const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{ - sign_prefix, - compiler_rt_operand_abbrev, - compiler_rt_dest_abbrev, + switch (dest_scalar_info.signedness) { + .signed => "", + .unsigned => "uns", + }, + compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)), + compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), }); - - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); - var result = try self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - - if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, ""); - if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, ""); - return result; + const result = try fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{operand_scalar_ty.toIntern()}, + .return_type = rt_int_ty.toIntern(), + }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); + return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), ""); } fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { @@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs }); const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs }); const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs }); - const zero = try o.builder.zeroInitValue(inst_llvm_ty); - const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero }); + const zero = if (isByRef(inst_ty, zcu)) zero: { + const zero = try o.builder.zeroInitConst(try o.lowerType(inst_ty, .in_memory)); + break :zero try o.lowerConstRef(zero, inst_ty.abiAlignment(zcu).toLlvm()); + } else try o.builder.zeroInitConst(try o.lowerType(inst_ty, .as_value)); + const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero.toValue() }); return self.wip.select(fast, ltz, c, a, ""); } if (scalar_ty.isSignedInt(zcu)) { @@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa); const allocator = bfa.allocator(); + const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); const scalar_bits = scalar_ty.intInfo(zcu).bits; var smin_big_int: std.math.big.int.Mutable = .{ .limbs = try allocator.alloc( @@ -3818,34 +3778,97 @@ fn airOverflow( } fn buildElementwiseCall( - self: *FuncGen, - llvm_fn: Builder.Function.Index, - args_vectors: []const Builder.Value, - result_vector: Builder.Value, - vector_len: usize, + fg: *FuncGen, + fn_name: Builder.StrtabString, + fn_info: Object.FuncInfo, + arg_values: []const Builder.Value, + vector_len: ?u32, ) Allocator.Error!Builder.Value { - const o = self.object; - assert(args_vectors.len <= 3); + const o = fg.object; + const zcu = o.zcu; + const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); - var i: usize = 0; - var result = result_vector; - while (i < vector_len) : (i += 1) { - const index_i32 = try o.builder.intValue(.i32, i); + const iterations = vector_len orelse 1; + const ret_ty: Type = .fromInterned(fn_info.return_type); + const ret_is_by_ref = isByRef(ret_ty, zcu); + if (iterations > 1 and (fn_info.return_type == .void_type or ret_is_by_ref) and + for (fn_info.param_types) |param_type| { + if (!isByRef(.fromInterned(param_type), zcu)) break false; + } else true) + { + const entry_block = fg.wip.cursor.block; + const loop_block = try fg.wip.block(2, "elementwise.loop"); + const done_block = try fg.wip.block(1, "elementwise.done"); - var args: [3]Builder.Value = undefined; - for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| { - arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, ""); + const result_ptr = if (fn_info.return_type == .void_type) .none else result_ptr: { + const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); + break :result_ptr try fg.buildAlloca( + if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, + ret_ty.abiAlignment(zcu).toLlvm(), + ); + }; + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const index = try fg.wip.phi(.i32, "elementwise.index"); + + var arg_elems_buf: [3]Builder.Value = undefined; + const arg_elems = arg_elems_buf[0..arg_values.len]; + for (arg_elems, fn_info.param_types, arg_values) |*arg_elem, param_type, arg_value| { + const arg_elem_ptr = try fg.ptraddScaled(arg_value, index.toValue(), Type.fromInterned(param_type).abiSize(zcu)); + arg_elem.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal); + } + const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems); + if (fn_info.return_type == .void_type) { + assert(result_elem == .none); + } else if (result_elem != .none) { + const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu)); + try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal); } - const result_elem = try self.wip.call( - .normal, - .ccc, - .none, - llvm_fn.typeOf(&o.builder), - llvm_fn.toValue(&o.builder), - args[0..args_vectors.len], - "", + + const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "elementwise.next_index"); + index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "elementwise.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + return result_ptr; + } + + var result = if (fn_info.return_type == .void_type) .none else if (ret_is_by_ref) result: { + const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); + break :result try fg.buildAlloca( + if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, + ret_ty.abiAlignment(zcu).toLlvm(), ); - result = try self.wip.insertElement(result, result_elem, index_i32, ""); + } else if (vector_len) |len| try o.builder.poisonValue( + try o.builder.vectorType(.normal, len, try o.lowerType(ret_ty, .as_value)), + ) else .none; + for (0..iterations) |index| { + const index_value = try o.builder.intValue(.i32, index); + var arg_elems_buf: [3]Builder.Value = undefined; + const arg_elems = arg_elems_buf[0..arg_values.len]; + for (arg_elems, fn_info.param_types, arg_values) |*arg_elem_value, param_type, arg_value| { + const arg_ty: Type = .fromInterned(param_type); + if (isByRef(arg_ty, zcu)) { + const arg_elem_ptr = try fg.ptraddConst(arg_value, index * arg_ty.abiSize(zcu)); + arg_elem_value.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal); + } else if (vector_len) |_| { + arg_elem_value.* = try fg.wip.extractElement(arg_value, index_value, "elementwise.arg_elem"); + } else arg_elem_value.* = arg_value; + } + const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems); + if (fn_info.return_type == .void_type) { + assert(result_elem == .none); + } else if (ret_is_by_ref) { + const result_elem_ptr = try fg.ptraddConst(result, index * ret_ty.abiSize(zcu)); + try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal); + } else if (vector_len) |_| { + result = try fg.wip.insertElement(result, result_elem, index_value, "elementwise.result"); + } else { + assert(result == .none); + result = result_elem; + } } return result; } @@ -3853,17 +3876,16 @@ fn buildElementwiseCall( /// Creates a floating point comparison by lowering to the appropriate /// hardware instruction or softfloat routine for the target fn buildFloatCmp( - self: *FuncGen, + fg: *FuncGen, fast: Builder.FastMathKind, pred: math.CompareOperator, ty: Type, params: [2]Builder.Value, ) Allocator.Error!Builder.Value { - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3874,53 +3896,33 @@ fn buildFloatCmp( .gt => .ogt, .gte => .oge, }; - return self.wip.fcmp(fast, cond, params[0], params[1], ""); + return fg.wip.fcmp(fast, cond, params[0], params[1], ""); } - const float_bits = scalar_ty.floatBits(target); - const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); - const fn_base_name = switch (pred) { - .neq => "ne", - .eq => "eq", - .lt => "lt", - .lte => "le", - .gt => "gt", - .gte => "ge", - }; - const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); - - const int_cond: Builder.IntegerCondition = switch (pred) { + const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ + switch (pred) { + .neq => "ne", + .eq => "eq", + .lt => "lt", + .lte => "le", + .gt => "gt", + .gte => "ge", + }, + compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)), + }); + const result = try fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, + .return_type = .i32_type, + }, ¶ms, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null); + return fg.wip.icmp(switch (pred) { .eq => .eq, .neq => .ne, .lt => .slt, .lte => .sle, .gt => .sgt, .gte => .sge, - }; - - if (ty.zigTypeTag(zcu) == .vector) { - const vec_len = ty.vectorLen(zcu); - const vector_result_ty = try o.builder.vectorType(.normal, vec_len, .i32); - - const init = try o.builder.poisonValue(vector_result_ty); - const result = try self.buildElementwiseCall(libc_fn, ¶ms, init, vec_len); - - const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0"); - return self.wip.icmp(int_cond, result, zero_vector, ""); - } - - const result = try self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - ¶ms, - "", - ); - return self.wip.icmp(int_cond, result, .@"0", ""); + }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), ""); } const FloatOp = enum { @@ -3949,32 +3951,26 @@ const FloatOp = enum { trunc, }; -const FloatOpStrat = union(enum) { - intrinsic: []const u8, - libc: Builder.String, -}; - /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) /// by lowering to the appropriate hardware instruction or softfloat /// routine for the target fn buildFloatOp( - self: *FuncGen, + fg: *FuncGen, comptime op: FloatOp, fast: Builder.FastMathKind, ty: Type, comptime params_len: usize, params: [params_len]Builder.Value, ) Allocator.Error!Builder.Value { - const o = self.object; + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try o.lowerType(ty, .as_value); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics - .neg => return self.wip.un(.fneg, params[0], ""), - .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) { + .neg => return fg.wip.un(.fneg, params[0], ""), + .add, .sub, .mul, .div, .fmod => return fg.wip.bin(switch (fast) { .normal => switch (op) { .add => .fadd, .sub => .fsub, @@ -4008,7 +4004,7 @@ fn buildFloatOp( .sqrt, .trunc, .fma, - => return self.wip.callIntrinsic(fast, .none, switch (op) { + => return fg.wip.callIntrinsic(fast, .none, switch (op) { .fmax => .maxnum, .fmin => .minnum, .ceil => .ceil, @@ -4026,36 +4022,152 @@ fn buildFloatOp( .trunc => .trunc, .fma => .fma, else => unreachable, - }, &.{llvm_ty}, ¶ms, ""), + }, &.{try o.lowerType(ty, .as_value)}, ¶ms, ""), .tan => unreachable, }; const float_bits = scalar_ty.floatBits(target); const fn_name = switch (op) { - .neg => { - // In this case we can generate a softfloat negation by XORing the - // bits with a constant. + // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation. + .neg, .fabs => if (isByRef(scalar_ty, zcu)) { + const is_vector = ty.toIntern() != scalar_ty.toIntern(); + const result_ptr = try fg.buildZigAlloca(ty, .none); + const entry_block = fg.wip.cursor.block; + const loop_block, const done_block, const llvm_usize_ty, const offset, const elem, const result_elem = if (is_vector) loop: { + const loop_block = try fg.wip.block(2, "neg_fabs.loop"); + const done_block = try fg.wip.block(1, "neg_fabs.done"); + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const llvm_usize_ty = try o.lowerType(.usize, .as_value); + const offset = try fg.wip.phi(llvm_usize_ty, "neg_fabs.offset"); + break :loop .{ + loop_block, + done_block, + llvm_usize_ty, + offset, + try fg.ptraddScaled(params[0], offset.toValue(), 1), + try fg.ptraddScaled(result_ptr, offset.toValue(), 1), + }; + } else .{ undefined, undefined, undefined, undefined, params[0], result_ptr }; + switch (scalar_ty.floatBits(target)) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.load( + try fg.ptraddConst(elem, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + .u64, + .normal, + ); + const exponent = try fg.load( + try fg.ptraddConst(elem, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + .u16, + .normal, + ); + const exponent_sign_bit: u16 = 1 << (16 - 1); + const updated_exponent = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, exponent, try o.builder.intValue(.i16, switch (op) { + else => unreachable, + .neg => exponent_sign_bit, + .fabs => exponent_sign_bit - 1, + }), "neg_fabs.updated_exponent"); + try fg.store( + try fg.ptraddConst(result_elem, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_elem, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + updated_exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.load( + try fg.ptraddConst(elem, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + .u64, + .normal, + ); + const hi = try fg.load( + try fg.ptraddConst(elem, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + .u64, + .normal, + ); + const hi_sign_bit: u64 = 1 << (64 - 1); + const updated_hi = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, hi, try o.builder.intValue(.i64, switch (op) { + else => unreachable, + .neg => hi_sign_bit, + .fabs => hi_sign_bit - 1, + }), "neg_fabs.updated_hi"); + try fg.store( + try fg.ptraddConst(result_elem, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_elem, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + updated_hi, + .u64, + .normal, + ); + }, + } + if (is_vector) { + const next_offset = try fg.wip.bin(.@"add nuw", offset.toValue(), try o.builder.intValue(llvm_usize_ty, scalar_ty.abiSize(zcu)), "neg_fabs.next_offset"); + offset.finish(&.{ try o.builder.intValue(llvm_usize_ty, 0), next_offset }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_offset, try o.builder.intValue(llvm_usize_ty, ty.abiSize(zcu)), "neg_fabs.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + } + return result_ptr; + } else { const int_ty = try o.builder.intType(@intCast(float_bits)); const cast_ty = switch (ty.zigTypeTag(zcu)) { .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty), else => int_ty, }; - const sign_mask = try o.builder.splatValue( - cast_ty, - try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)), - ); - const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, ""); - const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); - return self.wip.cast(.bitcast, result, llvm_ty, ""); + const sign_bit = @as(u128, 1) << @intCast(float_bits - 1); + const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) { + else => unreachable, + .neg => sign_bit, + .fabs => sign_bit - 1, + })); + const bitcasted_operand = try fg.wip.cast(.bitcast, params[0], cast_ty, ""); + const result = try fg.wip.bin(switch (op) { + else => unreachable, + .neg => .xor, + .fabs => .@"and", + }, bitcasted_operand, bitwise_rhs, ""); + const llvm_ty = try o.lowerType(ty, .as_value); + return fg.wip.cast(.bitcast, result, llvm_ty, ""); }, .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{ - @tagName(op), compilerRtFloatAbbrev(float_bits), + @tagName(op), compilerRtFloatAbbrev(target, float_bits), }), .ceil, .cos, .exp, .exp2, - .fabs, .floor, .fma, .fmax, @@ -4073,27 +4185,27 @@ fn buildFloatOp( libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), }), }; + return fg.buildElementwiseCall(fn_name, .{ + .cc = target.cCallingConvention().?, + .param_types = &@as([params_len]InternPool.Index, @splat(scalar_ty.toIntern())), + .return_type = scalar_ty.toIntern(), + }, ¶ms, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null); +} - const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); - const libc_fn = try o.getLibcFunction( - fn_name, - @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len], - scalar_llvm_ty, - ); - if (ty.zigTypeTag(zcu) == .vector) { - const result = try o.builder.poisonValue(llvm_ty); - return self.buildElementwiseCall(libc_fn, ¶ms, result, ty.vectorLen(zcu)); - } - - return self.wip.call( - fast.toCallKind(), - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - ¶ms, - "", - ); +/// Creates a floating point cast operation by lowering to the specified softfloat routine. +fn buildFloatCastCall( + fg: *FuncGen, + dest_ty: Type, + fn_name: Builder.StrtabString, + operand_ty: Type, + operand: Builder.Value, +) Allocator.Error!Builder.Value { + const zcu = fg.object.zcu; + return fg.buildElementwiseCall(fn_name, .{ + .cc = zcu.getTarget().cCallingConvention().?, + .param_types = &.{operand_ty.scalarType(zcu).toIntern()}, + .return_type = dest_ty.scalarType(zcu).toIntern(), + }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -4471,32 +4583,19 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); + const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_ty = self.typeOfIndex(inst); + const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { + if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); - } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); - - const dest_bits = dest_ty.floatBits(target); - const src_bits = operand_ty.floatBits(target); - const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ - compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), - }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - } + const dest_bits = dest_scalar_ty.floatBits(target); + const src_bits = operand_scalar_ty.floatBits(target); + const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ + compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), + }); + return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); } fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -4505,38 +4604,19 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); + const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_ty = self.typeOfIndex(inst); + const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { + if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); - } else { - const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); - const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); - - const dest_bits = dest_ty.scalarType(zcu).floatBits(target); - const src_bits = operand_ty.scalarType(zcu).floatBits(target); - const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ - compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), - }); - - const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); - if (dest_ty.isVector(zcu)) return self.buildElementwiseCall( - libc_fn, - &.{operand}, - try o.builder.poisonValue(dest_llvm_ty), - dest_ty.vectorLen(zcu), - ); - return self.wip.call( - .normal, - .ccc, - .none, - libc_fn.typeOf(&o.builder), - libc_fn.toValue(&o.builder), - &.{operand}, - "", - ); - } + const dest_bits = dest_scalar_ty.floatBits(target); + const src_bits = operand_scalar_ty.floatBits(target); + const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ + compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), + }); + return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); } fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { @@ -4558,10 +4638,143 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! // * bool/int/float <-> bool/int/float // * `@Vector(n, A)` <-> `@Vector(n, B)` // - // All of these cases can be handled by LLVM's `bitcast` instruction. + // Most of these cases can be handled by LLVM's `bitcast` instruction, except when + // a non-native type like `f80` is used. - assert(!isByRef(operand_ty, zcu)); - assert(!isByRef(dest_ty, zcu)); + if (isByRef(operand_ty, zcu)) { + const operand_scalar_ty = operand_ty.scalarType(zcu); + const target = zcu.getTarget(); + const bits = operand_scalar_ty.floatBits(target); + const dest_scalar_ty = dest_ty.scalarType(zcu); + if (isByRef(dest_ty, zcu)) { + assert(dest_scalar_ty.floatBits(target) == bits); + return operand; + } + assert(dest_scalar_ty.intInfo(zcu).bits == bits); + + const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) + operand_ty.vectorLen(zcu) + else + null; + const operand_scalar_size = operand_scalar_ty.abiSize(zcu); + var result = if (len) |_| + try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value)) + else + undefined; + for (0..len orelse 1) |index| { + const result_elem = result_elem: switch (bits) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + .u64, + .normal, + ); + const exponent = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + .u16, + .normal, + ); + const casted_mantissa = try fg.wip.cast(.zext, mantissa, .i80, "bitCast.casted_mantissa"); + const casted_exponent = try fg.wip.cast(.zext, exponent, .i80, "bitCast.casted_exponent"); + const shifted_exponent = try fg.wip.bin(.@"shl nuw", casted_exponent, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); + break :result_elem try fg.wip.bin(.@"or", casted_mantissa, shifted_exponent, "bitCast.result_elem"); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + .u64, + .normal, + ); + const hi = try fg.load( + try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + .u64, + .normal, + ); + const casted_lo = try fg.wip.cast(.zext, lo, .i128, "bitCast.casted_lo"); + const casted_hi = try fg.wip.cast(.zext, hi, .i128, "bitCast.casted_hi"); + const shifted_hi = try fg.wip.bin(.@"shl nuw", casted_hi, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); + break :result_elem try fg.wip.bin(.@"or", casted_lo, shifted_hi, "bitCast.result_elem"); + }, + }; + result = if (len) |_| + try fg.wip.insertElement(result, result_elem, try o.builder.intValue(.i32, index), "elementwise.result") + else + result_elem; + } + return result; + } + + if (isByRef(dest_ty, zcu)) { + const dest_scalar_ty = dest_ty.scalarType(zcu); + const bits = dest_scalar_ty.floatBits(zcu.getTarget()); + assert(dest_scalar_ty.isRuntimeFloat()); + const operand_scalar_ty = operand_ty.scalarType(zcu); + assert(operand_scalar_ty.intInfo(zcu).bits == bits); + + const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) + operand_ty.vectorLen(zcu) + else + null; + const operand_scalar_size = operand_scalar_ty.abiSize(zcu); + const result_ptr = try fg.buildZigAlloca(dest_ty, .none); + for (0..len orelse 1) |index| { + const operand_elem = if (len) |_| + try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem") + else + operand; + switch (bits) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.mantissa"); + const shifted_exponent = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); + const exponent = try fg.wip.cast(.@"trunc nuw", shifted_exponent, .i16, "bitCast.exponent"); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.lo"); + const shifted_hi = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); + const hi = try fg.wip.cast(.@"trunc nuw", shifted_hi, .i64, "bitCast.hi"); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + hi, + .u64, + .normal, + ); + }, + } + } + return result_ptr; + } const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); @@ -4730,7 +4943,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr_align = ptr_ty.ptrAlignment(zcu); const elem_ty = ptr_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { - return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue(); + return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue(); } return self.buildZigAlloca(elem_ty, ptr_align); } @@ -4743,7 +4956,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr_align = ptr_ty.ptrAlignment(zcu); const elem_ty = ptr_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { - return (try o.lowerPtrToVoid(ptr_align, ptr_ty.ptrAddressSpace(zcu))).toValue(); + return (try o.lowerPtrToVoid(ptr_align.toLlvm(), ptr_ty.ptrAddressSpace(zcu))).toValue(); } return self.buildZigAlloca(elem_ty, ptr_align); } @@ -4850,17 +5063,24 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu const elem = try fg.resolveInst(bin_op.rhs); if (ptr_info.flags.vector_index != .none) { - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. - const vec_ty = try fg.pt.vectorType(.{ - .len = ptr_info.packed_offset.host_size, - .child = elem_ty.toIntern(), - }); + if (isByRef(elem_ty, zcu)) { + const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu); + const elem_ptr = try fg.ptraddConst(ptr, offset); + try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind); + } else { + // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. + const vec_ty = try fg.pt.vectorType(.{ + .len = ptr_info.packed_offset.host_size, + .child = elem_ty.toIntern(), + }); - const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); - const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); - const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); + const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); + const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); + const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); + + try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); + } - try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); return .none; } @@ -4927,22 +5147,27 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { if (ptr_info.flags.is_volatile) .@"volatile" else .normal; if (ptr_info.flags.vector_index != .none) { - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. - const vec_ty = try fg.pt.vectorType(.{ - .len = ptr_info.packed_offset.host_size, - .child = elem_ty.toIntern(), - }); - const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); - const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); - return fg.wip.extractElement(vector_val, index_val, ""); + if (isByRef(elem_ty, zcu)) { + const elem_size = elem_ty.abiSize(zcu); + const offset = @backingInt(ptr_info.flags.vector_index) * elem_size; + const elem_ptr = try fg.ptraddConst(ptr, offset); + return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind); + } else { + // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. + const vec_ty = try fg.pt.vectorType(.{ + .len = ptr_info.packed_offset.host_size, + .child = elem_ty.toIntern(), + }); + const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); + const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); + return fg.wip.extractElement(vector_val, index_val, ""); + } } if (ptr_info.packed_offset.host_size == 0) { return fg.load(ptr, ptr_align, elem_ty, access_kind); } - assert(!isByRef(elem_ty, zcu)); // all packable types are by-val - // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. const backing_int_ty = try fg.pt.intType(.unsigned, @intCast(ptr_info.packed_offset.host_size * 8)); const llvm_backing_int_ty = try o.lowerType(backing_int_ty, .as_value); @@ -4952,6 +5177,67 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset); const shifted_value = try fg.wip.bin(.lshr, backing_int_val, shift_amt, ""); + + if (isByRef(elem_ty, zcu)) { + const result_ptr = try fg.buildZigAlloca(elem_ty, .none); + switch (elem_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 80 => { + const f80_layout = o.softF80Layout(.{}) catch unreachable; + const mantissa = try fg.wip.cast(.trunc, shifted_value, .i64, "load.mantissa"); + const shifted_exponent = try fg.wip.bin( + .lshr, + backing_int_val, + try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64), + "load.shifted_exponent", + ); + const exponent = try fg.wip.cast(.trunc, shifted_exponent, .i16, "load.exponent"); + + try fg.store( + try fg.ptraddConst(result_ptr, f80_layout.mantissa_offset), + f80_layout.alignment.offset(f80_layout.mantissa_offset), + mantissa, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, f80_layout.exponent_offset), + f80_layout.alignment.offset(f80_layout.exponent_offset), + exponent, + .u16, + .normal, + ); + }, + 128 => { + const f128_layout = o.softF128Layout(.{}) catch unreachable; + const lo = try fg.wip.cast(.trunc, shifted_value, .i64, "load.lo"); + const shifted_hi = try fg.wip.bin( + .lshr, + backing_int_val, + try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset + 64), + "load.shifted_hi", + ); + const hi = try fg.wip.cast(.trunc, shifted_hi, .i64, "load.hi"); + + try fg.store( + try fg.ptraddConst(result_ptr, f128_layout.lo_offset), + f128_layout.alignment.offset(f128_layout.lo_offset), + lo, + .u64, + .normal, + ); + try fg.store( + try fg.ptraddConst(result_ptr, f128_layout.hi_offset), + f128_layout.alignment.offset(f128_layout.hi_offset), + hi, + .u64, + .normal, + ); + }, + } + return result_ptr; + } + const elem_llvm_ty = try o.lowerType(elem_ty, .as_value); if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { @@ -5848,95 +6134,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val ); } -/// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result. -/// -/// Equivalent to: -/// ``` -/// var accum: T = init; -/// for (0..i) |i| { -/// accum = llvm_fn(accum, vec[i]); -/// } -/// // result is 'accum' -/// ``` -fn buildReducedCall( - self: *FuncGen, - llvm_fn: Builder.Function.Index, - operand_vector: Builder.Value, - vector_len: usize, - accum_init: Builder.Value, -) Allocator.Error!Builder.Value { - const o = self.object; - const llvm_usize_ty = try o.lowerType(.usize, .as_value); - const llvm_vector_len = try o.builder.intValue(llvm_usize_ty, vector_len); - const llvm_result_ty = accum_init.typeOfWip(&self.wip); - - const entry_block = self.wip.cursor.block; - - const cond_block = try self.wip.block(2, "ReduceLoopCond"); - const body_block = try self.wip.block(1, "ReduceLoopBody"); - const exit_block = try self.wip.block(1, "ReduceLoopExit"); - - _ = try self.wip.br(cond_block); - - // ReduceLoopCond: - // %index = phi iN [0, %Entry], [%new_index, %ReduceLoopBody] - // %accum = phi T [%accum_init, %Entry], [%new_accum, %ReduceLoopBody] - // %cond = icmp ult iN %index, %vector_len - // br i1 %cond, label %ReduceLoopBody, label %ReduceLoopExit - self.wip.cursor = .{ .block = cond_block }; - const index = try self.wip.phi(llvm_usize_ty, ""); - const accum = try self.wip.phi(llvm_result_ty, ""); - const cond = try self.wip.icmp(.ult, index.toValue(), llvm_vector_len, ""); - _ = try self.wip.brCond(cond, body_block, exit_block, .none); - - // ReduceLoopBody: - // %elem = extractelement %operand_vec, iN %index - // %new_accum = call T @llvm_fn(T %accum, T %elem) - // %new_index = add nuw iN %index, 1 - // br label %ReduceLoopCond - self.wip.cursor = .{ .block = body_block }; - const elem = try self.wip.extractElement(operand_vector, index.toValue(), ""); - const new_accum = try self.wip.call( - .normal, - .ccc, - .none, - llvm_fn.typeOf(&o.builder), - llvm_fn.toValue(&o.builder), - &.{ accum.toValue(), elem }, - "", - ); - const new_index = try self.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(llvm_usize_ty, 1), ""); - _ = try self.wip.br(cond_block); - - const index_init = try o.builder.intValue(llvm_usize_ty, 0); - index.finish(&.{ index_init, new_index }, &.{ entry_block, body_block }, &self.wip); - accum.finish(&.{ accum_init, new_accum }, &.{ entry_block, body_block }, &self.wip); - - self.wip.cursor = .{ .block = exit_block }; - return accum.toValue(); -} - -fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const o = self.object; +fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { + const o = fg.object; const zcu = o.zcu; const target = zcu.getTarget(); - const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce; - const operand = try self.resolveInst(reduce.operand); - const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); - const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try o.lowerType(scalar_ty, .as_value); + const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce; + const operand = try fg.resolveInst(reduce.operand); + const operand_ty = fg.typeOf(reduce.operand); + const scalar_ty = fg.typeOfIndex(inst); switch (reduce.operation) { - .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .And, .Or, .Xor => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .And => .@"vector.reduce.and", .Or => .@"vector.reduce.or", .Xor => .@"vector.reduce.xor", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .Min, .Max => switch (scalar_ty.zigTypeTag(zcu)) { - .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .Min => if (scalar_ty.isSignedInt(zcu)) .@"vector.reduce.smin" else @@ -5946,29 +6162,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A else .@"vector.reduce.umax", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .float => if (intrinsicsAllowed(scalar_ty, target)) - return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { + return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Min => .@"vector.reduce.fmin", .Max => .@"vector.reduce.fmax", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), else => unreachable, }, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) { - .int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { + .int => return fg.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { .Add => .@"vector.reduce.add", .Mul => .@"vector.reduce.mul", else => unreachable, - }, &.{llvm_operand_ty}, &.{operand}, ""), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), .float => if (intrinsicsAllowed(scalar_ty, target)) - return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { + return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Add => .@"vector.reduce.fadd", .Mul => .@"vector.reduce.fmul", else => unreachable, - }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) { - .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0), - .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0), + }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) { + .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0), + .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0), else => unreachable, }, operand }, ""), else => unreachable, @@ -5986,62 +6202,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), }), .Add => try o.builder.strtabStringFmt("__add{s}f3", .{ - compilerRtFloatAbbrev(float_bits), + compilerRtFloatAbbrev(target, float_bits), }), .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{ - compilerRtFloatAbbrev(float_bits), + compilerRtFloatAbbrev(target, float_bits), }), else => unreachable, }; - - const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty); - const init_val = switch (llvm_scalar_ty) { - .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast( - @as(f16, switch (reduce.operation) { - .Min, .Max => std.math.nan(f16), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), - .i80 => try o.builder.intValue(.i80, @as(i80, @bitCast( - @as(f80, switch (reduce.operation) { - .Min, .Max => std.math.nan(f80), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), - .i128 => try o.builder.intValue(.i128, @as(i128, @bitCast( - @as(f128, switch (reduce.operation) { - .Min, .Max => std.math.nan(f128), - .Add => -0.0, - .Mul => 1.0, - else => unreachable, - }), - ))), + const fn_info: Object.FuncInfo = .{ + .cc = target.cCallingConvention().?, + .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, + .return_type = scalar_ty.toIntern(), + }; + const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); + const init = switch (float_bits) { else => unreachable, + 16 => try o.f16Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f16), + .Add => -0.0, + .Mul => 1.0, + }), + 32 => try o.f32Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f32), + .Add => -0.0, + .Mul => 1.0, + }), + 64 => try o.f64Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f64), + .Add => -0.0, + .Mul => 1.0, + }), + 80 => try o.f80Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f80), + .Add => -0.0, + .Mul => 1.0, + }), + 128 => try o.f128Const(switch (reduce.operation) { + else => unreachable, + .Min, .Max => std.math.nan(f128), + .Add => -0.0, + .Mul => 1.0, + }), }; - return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(zcu), init_val); + const iterations = operand_ty.vectorLen(zcu); + const is_by_ref = isByRef(operand_ty, zcu); + if (iterations > 1 and is_by_ref) { + const init_ref = try o.lowerConstRef(init, scalar_ty.abiAlignment(zcu).toLlvm()); + + const entry_block = fg.wip.cursor.block; + const loop_block = try fg.wip.block(2, "reduce.loop"); + const done_block = try fg.wip.block(1, "reduce.loop"); + + _ = try fg.wip.br(loop_block); + + fg.wip.cursor = .{ .block = loop_block }; + const index = try fg.wip.phi(.i32, "reduce.index"); + const result = try fg.wip.phi(.ptr, "reduce.result"); + + const rhs_elem_ptr = try fg.ptraddScaled(operand, index.toValue(), scalar_ty.abiSize(zcu)); + const rhs_elem = try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal); + const next_result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result.toValue(), rhs_elem }); + + const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "reduce.next_index"); + index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip); + result.finish(&.{ init_ref.toValue(), next_result }, &.{ entry_block, loop_block }, &fg.wip); + const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "reduce.is_done"); + _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); + + fg.wip.cursor = .{ .block = done_block }; + return next_result; + } + var result = init.toValue(); + for (0..iterations) |index| { + const index_value = try o.builder.intValue(.i32, index); + const rhs_elem = if (is_by_ref) rhs_elem: { + const rhs_elem_ptr = try fg.ptraddConst(operand, index * scalar_ty.abiSize(zcu)); + break :rhs_elem try fg.load(rhs_elem_ptr, .none, scalar_ty, .normal); + } else try fg.wip.extractElement(operand, index_value, "reduce.rhs_elem"); + result = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, &.{ result, rhs_elem }); + } + return result; } -fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const o = self.object; +fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { + const o = fg.object; const zcu = o.zcu; const ip = &zcu.intern_pool; - const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; - const result_ty = self.typeOfIndex(inst); + const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl; + const result_ty = fg.typeOfIndex(inst); const len: usize = @intCast(result_ty.arrayLen(zcu)); - const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]); + const elements: []const Air.Inst.Ref = @ptrCast(fg.air.extra.items[ty_pl.payload..][0..len]); switch (result_ty.zigTypeTag(zcu)) { - .vector => { + .vector => if (isByRef(result_ty, zcu)) { + const elem_ty = result_ty.childType(zcu); + const elem_size = elem_ty.abiSize(zcu); + const result_ptr = try fg.buildZigAlloca(result_ty, .none); + for (elements, 0..) |elem, elem_index| { + const elem_ptr = try fg.ptraddConst(result_ptr, elem_index * elem_size); + const llvm_elem = try fg.resolveInst(elem); + try fg.store(elem_ptr, .none, llvm_elem, elem_ty, .normal); + } + return result_ptr; + } else { const llvm_result_ty = try o.lowerType(result_ty, .as_value); var vector = try o.builder.poisonValue(llvm_result_ty); - for (elements, 0..) |elem, i| { - const index_u32 = try o.builder.intValue(.i32, i); - const llvm_elem = try self.resolveInst(elem); - vector = try self.wip.insertElement(vector, llvm_elem, index_u32, ""); + for (elements, 0..) |elem, elem_index| { + const elem_index_val = try o.builder.intValue(.i32, elem_index); + const llvm_elem = try fg.resolveInst(elem); + vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, ""); } return vector; }, @@ -6057,18 +6330,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde for (elements, struct_type.field_types.get(ip)) |elem, field_ty| { if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; - const non_int_val = try self.resolveInst(elem); + const non_int_val = try fg.resolveInst(elem); const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu)); const small_int_ty = try o.builder.intType(ty_bit_size); const small_int_val = if (Type.fromInterned(field_ty).isPtrAtRuntime(zcu)) - try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") + try fg.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") else - try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); + try fg.wip.cast(.bitcast, non_int_val, small_int_ty, ""); const shift_rhs = try o.builder.intValue(int_ty, running_bits); const extended_int_val = - try self.wip.conv(.unsigned, small_int_val, int_ty, ""); - const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, ""); - running_int = try self.wip.bin(.@"or", running_int, shifted, ""); + try fg.wip.conv(.unsigned, small_int_val, int_ty, ""); + const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, ""); + running_int = try fg.wip.bin(.@"or", running_int, shifted, ""); running_bits += ty_bit_size; } return running_int; @@ -6078,19 +6351,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde // TODO in debug builds init to undef so that the padding will be 0xaa // even if we fully populate the fields. const struct_align = result_ty.abiAlignment(zcu); - const alloca_inst = try self.buildZigAlloca(result_ty, .none); + const alloca_inst = try fg.buildZigAlloca(result_ty, .none); for (elements, 0..) |elem, field_index| { if (result_ty.structFieldIsComptime(field_index, zcu)) continue; const field_ty = result_ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; const offset = result_ty.structFieldOffset(field_index, zcu); - const field_ptr = try self.ptraddConst(alloca_inst, offset); + const field_ptr = try fg.ptraddConst(alloca_inst, offset); const field_ptr_align = struct_align.offset(offset); - const llvm_field_val = try self.resolveInst(elem); + const llvm_field_val = try fg.resolveInst(elem); - try self.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal); + try fg.store(field_ptr, field_ptr_align, llvm_field_val, field_ty, .normal); } return alloca_inst; @@ -6099,21 +6372,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde .array => { assert(isByRef(result_ty, zcu)); - const alloca_inst = try self.buildZigAlloca(result_ty, .none); + const alloca_inst = try fg.buildZigAlloca(result_ty, .none); const array_info = result_ty.arrayInfo(zcu); const elem_size = array_info.elem_type.abiSize(zcu); for (elements, 0..) |elem, i| { - const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i); - const llvm_elem = try self.resolveInst(elem); - try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); + const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i); + const llvm_elem = try fg.resolveInst(elem); + try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); } if (array_info.sentinel) |sent_val| { - const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len); - const llvm_elem = try self.resolveValue(sent_val); - try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); + const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len); + const llvm_elem = try fg.resolveValue(sent_val); + try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); } return alloca_inst; @@ -6469,26 +6742,12 @@ fn store( .unsigned => .zext, .signed => .sext, }, elem, llvm_memory_ty, ""); - _ = try fg.wip.storeAtomic( - access_kind, - extended, - ptr, - fg.sync_scope, - .none, - llvm_ptr_align, - ); + _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align); return; } // `elem_ty` is a simple by-val type which requires no special handling. - _ = try fg.wip.storeAtomic( - access_kind, - elem, - ptr, - fg.sync_scope, - .none, - llvm_ptr_align, - ); + _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align); } fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { @@ -6650,7 +6909,8 @@ fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type { const ParamTypeIterator = struct { object: *Object, - fn_info: InternPool.Key.FuncType, + cc: std.lang.CallingConvention, + param_types: []const InternPool.Index, zig_index: u32, llvm_index: u32, types_len: u32, @@ -6672,63 +6932,66 @@ const ParamTypeIterator = struct { }; pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { - if (it.zig_index >= it.fn_info.param_types.len) return null; - const ip = &it.object.zcu.intern_pool; - const ty = it.fn_info.param_types.get(ip)[it.zig_index]; + if (it.zig_index >= it.param_types.len) return null; + const ty = it.param_types[it.zig_index]; it.byval_attr = false; return nextInner(it, Type.fromInterned(ty)); } /// `airCall` uses this instead of `next` so that it can take into account variadic functions. - fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { - const ip = &it.object.zcu.intern_pool; - if (it.zig_index >= it.fn_info.param_types.len) { - if (it.zig_index >= args.len) { + fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering { + if (it.zig_index >= it.param_types.len) { + if (it.zig_index >= arg_types.len) { return null; } else { - return nextInner(it, fg.typeOf(args[it.zig_index])); + return nextInner(it, .fromInterned(arg_types[it.zig_index])); } } else { - return nextInner(it, Type.fromInterned(it.fn_info.param_types.get(ip)[it.zig_index])); + return nextInner(it, .fromInterned(it.param_types[it.zig_index])); } } fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { const zcu = it.object.zcu; - const target = zcu.getTarget(); - + ty.assertHasLayout(zcu); if (!ty.hasRuntimeBits(zcu)) { it.zig_index += 1; return .no_bits; } - switch (it.fn_info.cc) { + switch (it.cc) { .@"inline" => unreachable, .auto => { it.zig_index += 1; it.llvm_index += 1; + + // Match the c calling convention in some cases to avoid llvm bugs. + const target = zcu.getTarget(); + if (target.cpu.arch == .x86_64 and ty.isVector(zcu) and ty.childType(zcu).toIntern() == .bool_type) return switch (ty.vectorLen(zcu)) { + 0 => .no_bits, + 1...32 => .abi_sized_int, + 33...64 => { + it.types_buffer[0..1].* = .{.double}; + it.offsets_buffer[0..2].* = .{ 0, 8 }; + it.types_len = 1; + return .multiple_llvm_types; + }, + else => .byval, + }; + if (ty.isSlice(zcu) or (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu))) { it.llvm_index += 1; return .slice; - } else if (isByRef(ty, zcu)) { - return .byref; - } else if (target.cpu.arch.isX86() and - !target.cpu.has(.x86, .avx512f) and - ty.totalVectorBits(zcu) >= 512) - { - // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns - // "512-bit vector arguments require 'avx512f' for AVX512" - return .byref; - } else { - return .byval; } + if (isByRef(ty, zcu)) return .byref; + return .byval; }, .async => { @panic("TODO implement async function lowering in the LLVM backend"); }, - .x86_64_sysv, .x86_64_x32 => return it.nextSystemV(ty), - .x86_64_win => return it.nextWin64(ty), + .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), + .x86_64_win => return it.next_x86_64_win(ty), .x86_stdcall => { it.zig_index += 1; it.llvm_index += 1; @@ -6748,9 +7011,9 @@ const ParamTypeIterator = struct { .float_array => |len| return Lowering{ .float_array = len }, .byval => return .byval, .integer => { - it.types_len = 1; it.types_buffer[0..1].* = .{.i64}; it.offsets_buffer[0..2].* = .{ 0, 8 }; + it.types_len = 1; return .multiple_llvm_types; }, .double_integer => return Lowering{ .i64_array = 2 }, @@ -6857,7 +7120,7 @@ const ParamTypeIterator = struct { } } - fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { + fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering { const zcu = it.object.zcu; switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) { .integer => { @@ -6898,113 +7161,108 @@ const ParamTypeIterator = struct { } } - fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { - const zcu = it.object.zcu; - const ip = &zcu.intern_pool; - ty.assertHasLayout(zcu); - const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); - if (classes[0] == .memory) { - it.zig_index += 1; - it.llvm_index += 1; - it.byval_attr = true; - return .byref; - } - if (isScalar(zcu, ty)) { - it.zig_index += 1; - it.llvm_index += 1; - return .byval; - } - var types_index: u32 = 0; - var offset: u64 = 0; - for (classes) |class| { - switch (class) { - .integer => { - it.types_buffer[types_index] = .i64; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .sse => { - it.types_buffer[types_index] = .double; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .sseup => { - if (it.types_buffer[types_index - 1] == .double) { - it.types_buffer[types_index - 1] = .fp128; - } else { - it.types_buffer[types_index] = .double; - it.offsets_buffer[types_index] = offset; - types_index += 1; + fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering { + const o = it.object; + const zcu = o.zcu; + const target = zcu.getTarget(); + const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg); + var types_len: u32 = 0; + const classes_len = for (classes, 0..) |class, class_index| switch (class) { + .integer => { + it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64)); + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .sse => { + it.types_buffer[types_len] = .double; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .sseup => { + if (it.types_buffer[types_len - 1] == .double) { + if (ty.isVector(zcu)) { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; } - }, - .float => { - it.types_buffer[types_index] = .float; - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .float_combine => { - it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); - it.offsets_buffer[types_index] = offset; - types_index += 1; - }, - .x87 => { - it.zig_index += 1; - it.llvm_index += 1; - it.byval_attr = true; - return .byref; - }, - .x87up => unreachable, - .none => break, - .memory => unreachable, // handled above - .win_i128 => unreachable, // windows only - .bool_vector_mask, - .integer_per_element, - .sse_per_element, - .sse_sse_x87_per_qword, - .sse_per_xword, - .sse_per_yword, - .sse_per_zword, - => unreachable, // vectors already handled by `isScalar` above - } - offset += 8; - } - const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); - if (first_non_integer == null or classes[first_non_integer.?] == .none) { - assert(first_non_integer orelse classes.len == types_index); - if (types_index == 1) { + it.types_buffer[types_len - 1] = .fp128; + } else { + it.types_buffer[types_len] = .double; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + } + }, + .float => { + it.types_buffer[types_len] = .float; + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .float_combine => { + it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float); + it.offsets_buffer[types_len] = 8 * class_index; + types_len += 1; + }, + .x87 => { it.zig_index += 1; it.llvm_index += 1; - return .abi_sized_int; - } - if (it.llvm_index + types_index > 6) { + it.byval_attr = true; + return .byref; + }, + .x87up => unreachable, + .none => break class_index, + .memory => { + it.zig_index += 1; + it.llvm_index += 1; + it.byval_attr = true; + return .byref; + }, + .win_i128 => unreachable, // windows only + .bool_vector_mask, + .integer_per_element, + .sse_per_element, + .sse_sse_x87_per_qword, + .sse_per_xword, + .sse_per_yword, + .sse_per_zword, + => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + } else classes.len; + if (types_len > 1) { + if (it.llvm_index + classes_len > 6) { it.zig_index += 1; it.llvm_index += 1; it.byval_attr = true; return .byref; } - switch (ip.indexToKey(ty.toIntern())) { - .struct_type => { - const size = ty.abiSize(zcu); - assert(@divCeil(size, 8) == types_index); - if (size % 8 > 0) { - it.types_buffer[types_index - 1] = - try it.object.builder.intType(@intCast(size % 8 * 8)); - } - }, - else => {}, + } else if (!isByRef(ty, zcu)) { + const llvm_ty = try o.lowerType(ty, .as_value); + if (it.types_buffer[0] == llvm_ty or + (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder))) + { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; } } - it.offsets_buffer[types_index] = offset; - it.types_len = types_index; - it.llvm_index += types_index; + it.offsets_buffer[types_len] = 8 * classes_len; + it.types_len = types_len; + it.llvm_index += types_len; it.zig_index += 1; return .multiple_llvm_types; } }; -pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator { +pub fn iterateParamTypes( + object: *Object, + cc: std.lang.CallingConvention, + param_types: []const InternPool.Index, +) ParamTypeIterator { return .{ .object = object, - .fn_info = fn_info, + .cc = cc, + .param_types = param_types, .zig_index = 0, .llvm_index = 0, .types_len = undefined, @@ -7035,35 +7293,34 @@ pub const FnReturnStrat = union(enum) { /// In order to support the C calling convention, some return types need to be lowered /// completely differently in the function prototype to honor the C ABI, and then /// be effectively bitcasted to the actual return type. -pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ret_ty: Type = .fromInterned(fn_info.return_type); ret_ty.assertHasLayout(zcu); if (!ret_ty.hasRuntimeBits(zcu)) return .void; - switch (fn_info.cc) { + switch (cc) { .@"inline" => unreachable, .auto => { + // Match the c calling convention in some cases to avoid llvm bugs. + const target = zcu.getTarget(); + if (target.cpu.arch == .x86_64 and ret_ty.isVector(zcu) and ret_ty.childType(zcu).toIntern() == .bool_type) return switch (ret_ty.vectorLen(zcu)) { + 0 => .void, + 1...8 => .{ .mem_cast = .i8 }, + 9...16 => .{ .mem_cast = .i16 }, + 17...32 => .{ .mem_cast = .i32 }, + 33...64 => .{ .mem_cast = .double }, + else => .by_val, + }; + if (isByRef(ret_ty, zcu)) return .sret; - - const target = zcu.getTarget(); - if (target.cpu.arch.isX86() and - !target.cpu.has(.x86, .avx512f) and - ret_ty.totalVectorBits(zcu) >= 512) - { - // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns - // "512-bit vector arguments require 'avx512f' for AVX512" - return .sret; - } - return .by_val; }, - .x86_64_sysv, .x86_64_x32 => return lowerSystemVFnRetTy(o, fn_info), - .x86_64_win => return lowerWin64FnRetTy(o, fn_info), + .x86_64_sysv, .x86_64_x32 => return fnReturnStrat_x86_64_sysv(o, ret_ty), + .x86_64_win => return fnReturnStrat_x86_64_win(o, ret_ty), .x86_stdcall => if (isScalar(zcu, ret_ty)) { assert(!isByRef(ret_ty, zcu)); return .by_val; } else return .sret, - .x86_fastcall => return lowerX86FastcallFnRetTy(o, zcu, ret_ty), + .x86_fastcall => return fnReturnStrat_x86_fastcall(o, zcu, ret_ty), .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) { .memory => return .sret, @@ -7124,7 +7381,7 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err } } -fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { if (isScalar(zcu, ty)) { assert(!isByRef(ty, zcu)); return .by_val; @@ -7139,9 +7396,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe return .sret; } -fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_64_win(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ret_ty = Type.fromInterned(fn_info.return_type); switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) { .integer => if (isScalar(zcu, ret_ty)) { assert(!isByRef(ret_ty, zcu)); @@ -7174,78 +7430,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err } } -fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { +fn fnReturnStrat_x86_64_sysv(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { const zcu = o.zcu; - const ip = &zcu.intern_pool; - const ret_ty = Type.fromInterned(fn_info.return_type); - if (isScalar(zcu, ret_ty)) { - assert(!isByRef(ret_ty, zcu)); - return .by_val; - } const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret); - var types_index: u32 = 0; var types_buffer: [8]Builder.Type = undefined; - for (classes) |class| { - switch (class) { - .integer => { - types_buffer[types_index] = .i64; - types_index += 1; - }, - .sse => { - types_buffer[types_index] = .double; - types_index += 1; - }, - .sseup => { - if (types_buffer[types_index - 1] == .double) { - types_buffer[types_index - 1] = .fp128; - } else { - types_buffer[types_index] = .double; - types_index += 1; - } - }, - .float => { - types_buffer[types_index] = .float; - types_index += 1; - }, - .float_combine => { - types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float); - types_index += 1; - }, - .x87 => { - if (types_index != 0 or classes[2] != .none) return .sret; - types_buffer[types_index] = .x86_fp80; - types_index += 1; - }, - .x87up => continue, - .none => break, - .memory => return .sret, - .win_i128 => unreachable, // windows only - .bool_vector_mask, - .integer_per_element, - .sse_per_element, - .sse_sse_x87_per_qword, - .sse_per_xword, - .sse_per_yword, - .sse_per_zword, - => unreachable, // vectors already handled by `isScalar` above - } + var types_len: u32 = 0; + for (classes, 0..) |class, class_index| switch (class) { + .integer => { + types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64)); + types_len += 1; + }, + .sse => { + types_buffer[types_len] = .double; + types_len += 1; + }, + .sseup => { + if (types_buffer[types_len - 1] == .double) { + if (ret_ty.isVector(zcu)) return .by_val; + types_buffer[types_len - 1] = .fp128; + } else { + types_buffer[types_len] = .double; + types_len += 1; + } + }, + .float => { + types_buffer[types_len] = .float; + types_len += 1; + }, + .float_combine => { + types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float); + types_len += 1; + }, + .x87 => { + if (types_len > 0 or classes[2] != .none) return .sret; + types_buffer[types_len] = .x86_fp80; + types_len += 1; + }, + .x87up => continue, + .none => break, + .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret, + .win_i128 => unreachable, // windows only + .bool_vector_mask, + .integer_per_element, + .sse_per_element, + .sse_sse_x87_per_qword, + .sse_per_xword, + .sse_per_yword, + .sse_per_zword, + => return .by_val, + }; + if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) }; + if (!isByRef(ret_ty, zcu)) { + const llvm_ty = try o.lowerType(ret_ty, .as_value); + if (types_buffer[0] == llvm_ty) return .by_val; + if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val; + if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and + llvm_ty.vectorLen(&o.builder) == 1 and + llvm_ty.scalarType(&o.builder) == .double) return .by_val; } - const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); - if (first_non_integer == null or classes[first_non_integer.?] == .none) { - assert(first_non_integer orelse classes.len == types_index); - switch (ip.indexToKey(ret_ty.toIntern())) { - .struct_type => { - const size = ret_ty.abiSize(zcu); - assert(@divCeil(size, 8) == types_index); - if (size % 8 > 0) { - types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8)); - } - }, - else => {}, - } - if (types_index == 1) return .{ .mem_cast = types_buffer[0] }; - } - return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_index]) }; + return .{ .mem_cast = types_buffer[0] }; } /// This function deliberately does not handle `_BitInt` because it typically @@ -7258,15 +7501,22 @@ pub fn ccAbiPromoteInt(cc: std.lang.CallingConvention, zcu: *Zcu, ty: Type) ?std else => {}, } - const ty_tag = ty.zigTypeTag(zcu); - const int_info = switch (ty_tag) { - .bool => Type.u1.intInfo(zcu), - else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null, - }; - - assert(int_info.bits == 0 or (int_info.bits == 1 and ty_tag == .bool) or std.math.isPowerOfTwo(int_info.bits)); - const target = zcu.getTarget(); + const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type) + .{ .signedness = .unsigned, .bits = 1 } + else if (ty.isAbiInt(zcu)) + ty.intInfo(zcu) + else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => return null, + .soft => .{ .signedness = .unsigned, .bits = bits }, + }, + 80, 128 => return null, + } else return null; + + assert(int_info.bits == 0 or (int_info.bits == 1 and ty.toIntern() == .bool_type) or std.math.isPowerOfTwo(int_info.bits)); + return switch (target.cpu.arch) { .aarch64, .aarch64_be, @@ -7362,15 +7612,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool { .void, .bool, .int, - .float, .pointer, .error_set, .@"fn", .@"enum", - .vector, .@"anyframe", => false, + .float, .vector => { + const target = zcu.getTarget(); + const scalar_ty = ty.scalarType(zcu); + return if (scalar_ty.isRuntimeFloat()) switch (scalar_ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => false, + 80, 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => false, + .soft => true, + }, + } else false; + }, + .array, .frame, => ty.hasRuntimeBits(zcu), @@ -7431,12 +7692,19 @@ fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, ""); } -fn compilerRtIntBits(bits: u16) ?u16 { - inline for (.{ 32, 64, 128 }) |b| { - if (bits <= b) { - return b; - } - } +fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type { + if (int_info.bits <= 32) return switch (int_info.signedness) { + .signed => .i32, + .unsigned => .u32, + }; + if (int_info.bits <= 64) return switch (int_info.signedness) { + .signed => .i64, + .unsigned => .u64, + }; + if (int_info.bits <= 128) return switch (int_info.signedness) { + .signed => .i128, + .unsigned => .u128, + }; return null; } @@ -7495,13 +7763,12 @@ fn appendConstraints( } /// LLVM does not support all relevant intrinsics for all targets, so we -/// may need to manually generate a compiler-rt call. +/// may need to manually generate a compiler-rt call using a soft type. fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool { - return switch (scalar_ty.toIntern()) { - .f16_type => llvm.backendSupportsF16(target), - .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target), - .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target), - else => true, + if (!scalar_ty.isRuntimeFloat()) return true; + return switch (std.zig.target.compilerRtFloatAbi(target, scalar_ty.floatBits(target))) { + .hard => true, + .soft => false, }; } diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig index f512f1e6db98031dd581bc9cb19ef7be42b7ae29..e7c07582030cc16d73f07b0d56d56f09f0607a0f 100644 --- a/src/codegen/mips/abi.zig +++ b/src/codegen/mips/abi.zig @@ -38,7 +38,14 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { return .byval; }, .bool => return .byval, - .float => return .byval, + .float => return switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64 => .byval, + 80, 128 => switch (max_direct_size) { + else => unreachable, + 64 => .memory, + }, + }, .int, .@"enum", .error_set => { return .byval; }, diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 4ee131d079c666a52516e480137782e44f45a553..aed925be2953ddfb56581b9bb5eef521e8b78507 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -5036,7 +5036,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void { .register_pair, => { if (ret_ty.isVector(zcu)) { - const bit_size = ret_ty.totalVectorBits(zcu); + const bit_size = ret_ty.bitSize(zcu); // set the vtype to hold the entire vector's contents in a single element try func.setVl(.zero, 0, .{ @@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! // size to the total size of the vector, and vmv.x.s will work then if (src_reg.class() == .vector) { try func.setVl(.zero, 0, .{ - .vsew = switch (ty.totalVectorBits(zcu)) { + .vsew = switch (ty.bitSize(zcu)) { 8 => .@"8", 16 => .@"16", 32 => .@"32", diff --git a/src/codegen/riscv64/abi.zig b/src/codegen/riscv64/abi.zig index 5c89a35f7bd4e718e8e032093856f6068b751c9b..154118c50c98572fea63fcc00986c7cc338b3ca6 100644 --- a/src/codegen/riscv64/abi.zig +++ b/src/codegen/riscv64/abi.zig @@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { return .integer; }, .bool => return .integer, - .float => return .byval, .int, .@"enum", .error_set => { const bit_size = ty.bitSize(zcu); if (bit_size > max_byval_size) return .memory; return .byval; }, + .float => return switch (ty.floatBits(target)) { + else => unreachable, + 16, 32, 64, 128 => .byval, + 80 => switch (max_byval_size) { + else => unreachable, + 64 => .memory, + 128 => .double_integer, + }, + }, .vector => { const bit_size = ty.bitSize(zcu); if (bit_size > max_byval_size) return .memory; @@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass { }, .vector => { // we pass vectors through integer registers if they are small enough to fit. - const vec_bits = ty.totalVectorBits(zcu); + const vec_bits = ty.bitSize(zcu); if (vec_bits <= 64) { result[0] = .integer; return result; diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig index 6fb81d3e6b8792566b9c69156ca63a67ed788299..7b35245fdad37be5e062bbcc873c116a78a99152 100644 --- a/src/codegen/s390x/abi.zig +++ b/src/codegen/s390x/abi.zig @@ -38,9 +38,11 @@ pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class { 1...64 => .simple, else => .pointer, }, - .float => return switch (ty.floatBits(zcu.getTarget())) { - 16, 32, 64 => .double_or_float, - else => .pointer, + .float => switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64 => return .double_or_float, + 80 => {}, + 128 => return .pointer, }, .pointer, .optional => return .simple, .array => switch (ty.arrayLen(zcu)) { diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 3dc36619686e53a6112e3cc81ec9ccd3f902e0c6..2848a5f2573c75c73036aa2ff19f583403a9085f 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment; const errUnionPayloadOffset = codegen.errUnionPayloadOffset; const errUnionErrorOffset = codegen.errUnionErrorOffset; -const target_util = @import("../../target.zig"); -const libcFloatPrefix = target_util.libcFloatPrefix; -const libcFloatSuffix = target_util.libcFloatSuffix; -const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; -const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; - pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { return comptime &.initMany(&.{ .expand_bit_cast_safe, @@ -2515,15 +2509,15 @@ const IntType = struct { .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() }, .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() }, .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() }, - .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) }, - .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) }, - .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) }, - .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) }, - .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) }, - .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) }, - .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) }, - .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) }, - .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) }, + .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? }, + .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? }, + .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? }, + .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? }, + .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? }, + .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? }, + .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? }, + .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? }, + .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? }, .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable, }, diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig index 7a643e8dc7a755937f096f9826e5d770c2394b42..244b2c7719476ffa1542ce5863c11ac62c3c36de 100644 --- a/src/codegen/wasm/abi.zig +++ b/src/codegen/wasm/abi.zig @@ -25,7 +25,11 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { assert(ty.hasRuntimeBits(zcu)); switch (ty.zigTypeTag(zcu)) { .int, .@"enum", .error_set => return .{ .direct = ty }, - .float => return .{ .direct = ty }, + .float => return switch (ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16, 32, 64, 128 => .{ .direct = ty }, + 80 => .indirect, + }, .bool => return .{ .direct = ty }, .vector => return .{ .direct = ty }, .array => return .indirect, diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index da82d324608abdc1a1dabc4c691c41b4f9c470d5..662fc600b1e863b89bdfc0f8719545786ac64dac 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -182636,15 +182636,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int { .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() }, .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, - .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) }, - .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) }, - .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) }, - .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) }, - .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) }, - .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) }, - .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) }, - .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) }, - .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) }, + .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? }, + .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? }, + .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? }, + .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? }, + .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? }, + .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? }, + .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? }, + .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? }, + .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? }, .f16, .f32, .f64, .f80, .f128, .c_longdouble => null, .anyopaque, .void, diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 3e7a9a548d54baee16d64a54de9a42c4650f7ea5..0bff5bd60a2f7e918dda9fd5835d653378686cff 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -133,7 +133,7 @@ pub fn classifyWindows(init_ty: Type, zcu: *Zcu, target: *const std.Target, ctx: .float => switch (ty.floatBits(target)) { 16, 32, 64 => .sse, 80 => .memory, - 128 => if (ctx == .arg) .memory else .sse, + 128 => .win_i128, else => unreachable, }, .vector => { @@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont }; const unaligned_size = elem_ty.abiSize(zcu) * len; if (unaligned_size <= 4) return Class.one_integer; - if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and - elem_ty.isRuntimeFloat()) return Class.stack; // what + if (unaligned_size == 8 * 1 * 1 and len == 1) { + if (ctx == .arg and elem_ty.isRuntimeFloat()) return Class.stack; // what? + if (ctx != .other and !elem_ty.isRuntimeFloat() and target.os.tag == .freebsd) return Class.one_integer; // who? + } if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none }; if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none }; if (!target.cpu.has(.x86, .avx)) { if (ctx == .ret) switch (unaligned_size) { else => {}, 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{ - .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how - } else Class.len_integers, // why + .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how? + } else Class.len_integers, // why? 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none }, }; return Class.stack; diff --git a/src/libs/mingw/Preprocessor.zig b/src/libs/mingw/Preprocessor.zig index dcf8e01d043dbc6790aeff839718fd65b5e621cd..9098b6013a4179ba15de85707d70d290f09bd116 100644 --- a/src/libs/mingw/Preprocessor.zig +++ b/src/libs/mingw/Preprocessor.zig @@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void { fn defineBuiltins(pp: *Preprocessor) !void { var buf: [5]u8 = undefined; - var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.longdouble)}) catch unreachable; + var val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.longdouble).?}) catch unreachable; try pp.defineBuiltinValue("__SIZEOF_LONG_DOUBLE__", val, .pp_num); - val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeBitSize(.double)}) catch unreachable; + val = std.fmt.bufPrint(&buf, "{d}", .{pp.target.cTypeByteSize(.double).?}) catch unreachable; try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num); if (pp.target.abi.isGnu()) { diff --git a/src/target.zig b/src/target.zig index e249be39947d8d99f6f9eef6bd15b271887625fe..b4dc16b3185bb4e60ec99d93e2a39595f815eeed 100644 --- a/src/target.zig +++ b/src/target.zig @@ -881,13 +881,13 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 { }; } -pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 { +pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 { return switch (float_bits) { 16 => "h", 32 => "s", 64 => "d", 80 => "x", - 128 => "t", + 128 => if (target.cpu.arch.isPowerPC()) "k" else "t", else => unreachable, }; } diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 957ac6b1796c3ce962c139fc3669c4760c8ede87..d79d2d07ba75c4660478753dc4d9a23d48fdfe2c 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -129,8 +129,7 @@ test "alignment and size of structs with 128-bit fields" { y: u8, }; const expected = switch (builtin.cpu.arch) { - .s390x, - => .{ + .s390x => .{ .a_align = 8, .a_size = 16, @@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" { .u129_align = 8, .u129_size = 24, }, + .x86 => switch (builtin.os.tag) { + else => .{ + .a_align = 4, + .a_size = 16, + .b_align = 4, + .b_size = 20, + + .u128_align = 4, + .u128_size = 16, + .u129_align = 4, + .u129_size = 20, + }, + .uefi, .windows => .{ + .a_align = 8, + .a_size = 16, + + .b_align = 8, + .b_size = 24, + + .u128_align = 8, + .u128_size = 16, + .u129_align = 8, + .u129_size = 24, + }, + }, .amdgcn, .arm, .armeb, @@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" { .powerpc, .powerpcle, .riscv32, + .sparc, => .{ .a_align = 8, .a_size = 16, - .b_align = 16, - .b_size = 32, + .b_align = 8, + .b_size = 24, .u128_align = 8, .u128_size = 16, @@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" { .nvptx64, .powerpc64, .powerpc64le, - .sparc, .sparc64, .riscv64, .wasm32, .wasm64, - .x86, .x86_64, => .{ .a_align = 16, @@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" { else => return error.SkipZigTest, }; - const min_struct_align = if (builtin.zig_backend == .stage2_c) if (builtin.cpu.arch == .s390x) 8 else 16 else 0; comptime { - assert(@alignOf(A) == @max(expected.a_align, min_struct_align)); + assert(@alignOf(A) == expected.a_align); assert(@sizeOf(A) == expected.a_size); - assert(@alignOf(B) == @max(expected.b_align, min_struct_align)); + assert(@alignOf(B) == expected.b_align); assert(@sizeOf(B) == expected.b_size); assert(@alignOf(u128) == expected.u128_align); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 4cbe2f1aed593d513d58691ec7baf5613494f9e7..697da63db23d14bb9e583745c80c8aca350d8a8d 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -181,6 +181,7 @@ test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; const S = struct { fn doTheTest(comptime Int: type) !void { @@ -204,7 +205,7 @@ test "@floatFromInt(f80)" { try S.doTheTest(i64); try S.doTheTest(i80); try S.doTheTest(i128); - // try S.doTheTest(i256); // TODO missing compiler_rt symbols + try S.doTheTest(i256); try comptime S.doTheTest(i31); try comptime S.doTheTest(i32); try comptime S.doTheTest(i45); diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 7e9f58e46b0cfa6632234c2136344da6240f468f..ea01c8a88fe3ebf590d71027a7a5516cd57eeedb 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void { test "cmp f16" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f16); try comptime testCmp(f16); @@ -127,7 +126,6 @@ test "cmp f16" { test "cmp f32" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f32); try comptime testCmp(f32); @@ -1173,11 +1171,6 @@ test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testFloor(f80); try comptime testFloor(f80); try testFloor(f128); @@ -1261,11 +1254,6 @@ test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testCeil(f80); try comptime testCeil(f80); try testCeil(f128); @@ -1280,11 +1268,6 @@ test "@ceil f80 maxInt(u64)" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - var x: u64 = std.math.maxInt(u64); x = x; const float: f80 = @floatFromInt(x); @@ -1366,11 +1349,6 @@ test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - try testTrunc(f80); try comptime testTrunc(f80); try testTrunc(f128); diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 8750c7723149a9c772ec2dae6aaeda0b4ba03f8b..e76ca9850f3ce2bc9ca356910e76407dfae07fb1 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -2142,11 +2142,6 @@ test "remainder division" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12602 - return error.SkipZigTest; - } - if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest; try comptime remdiv(f16); @@ -2337,7 +2332,6 @@ test "NaN comparison" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testNanEqNan(f16); try testNanEqNan(f32); diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 9f8d277774f278dd2e7ee138e5d54e52fbfaa491..5838231e75ed214364a9a1af0527e5b9e480eaa9 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -774,6 +774,8 @@ test "vector reduce operation" { try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9)); try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9)); try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9)); + try testReduce(.Add, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 42.9)); + try testReduce(.Add, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 42.9)); try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false)); try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0)); @@ -792,6 +794,8 @@ test "vector reduce operation" { try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0)); try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0)); try testReduce(.Min, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, -100.0)); + try testReduce(.Min, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, -100.0)); + try testReduce(.Min, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, -100.0)); try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4)); try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4)); @@ -804,6 +808,8 @@ test "vector reduce operation" { try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9)); try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9)); try testReduce(.Max, [4]f64{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f64, 10.0e9)); + try testReduce(.Max, [4]f80{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f80, 10.0e9)); + try testReduce(.Max, [4]f128{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f128, 10.0e9)); try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24)); try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24)); @@ -816,6 +822,8 @@ test "vector reduce operation" { try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7)); try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7)); try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7)); + try testReduce(.Mul, [4]f80{ -1.9, 5.1, -60.3, 100.0 }, @as(f80, 58430.7)); + try testReduce(.Mul, [4]f128{ -1.9, 5.1, -60.3, 100.0 }, @as(f128, 58430.7)); try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true)); try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1)); @@ -823,6 +831,7 @@ test "vector reduce operation" { try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0)); try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff)); try testReduce(.Or, [4]u128{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u128, 0xffffffff)); + try testReduce(.Or, [4]u80{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u80, 0xffffffff)); try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true)); try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1)); @@ -835,22 +844,32 @@ test "vector reduce operation" { const f16_nan = math.nan(f16); const f32_nan = math.nan(f32); const f64_nan = math.nan(f64); + const f80_nan = math.nan(f80); + const f128_nan = math.nan(f128); try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); try testReduce(.Add, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); + try testReduce(.Add, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan); + try testReduce(.Add, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan); try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9)); try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9)); try testReduce(.Min, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, -1.9)); + try testReduce(.Min, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, -1.9)); + try testReduce(.Min, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, -1.9)); try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0)); try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0)); try testReduce(.Max, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, @as(f64, 100.0)); + try testReduce(.Max, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, @as(f80, 100.0)); + try testReduce(.Max, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, @as(f128, 100.0)); try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); try testReduce(.Mul, [4]f64{ -1.9, 5.1, f64_nan, 100.0 }, f64_nan); + try testReduce(.Mul, [4]f80{ -1.9, 5.1, f80_nan, 100.0 }, f80_nan); + try testReduce(.Mul, [4]f128{ -1.9, 5.1, f128_nan, 100.0 }, f128_nan); } }; @@ -1319,11 +1338,6 @@ test "byte vector initialized in inline function" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and comptime builtin.cpu.has(.x86, .avx512f)) { - // TODO https://github.com/ziglang/zig/issues/13279 - return error.SkipZigTest; - } - const S = struct { fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) { return .{ e0, e1, e2, e3 }; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index acd8c258649e3cccadadbd4390d8f9b0cf0999a6..101e07c97ccf7a4c9c2cd702c545b7898f858082 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -408,7 +408,11 @@ void c_test_longdouble(void) { zig_8_longdouble(0, 1, 2, 3, 4, 5, 6, 7, 10, 9); } -#if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__) +#ifndef __hexagon__ +#ifndef __loongarch__ +#ifndef __mips__ +#ifndef ZIG_PPC64 +#if !(defined(__i386__) && defined(_WIN32)) typedef bool Vector_2_bool __attribute__((ext_vector_type(2))); @@ -4657,6 +4661,10 @@ void c_test_vector_512_bool(void) { }); } +#endif +#endif +#endif +#endif #endif typedef uint8_t Vector_1_u8 __attribute__((vector_size(1 * sizeof(uint8_t)))); diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 387eeb88c20b4ebfa9646ff10fde7322db299302..1f9b5a9f2ab04f4d3269a1ff6058d1d15ae2a63c 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -451,8 +451,11 @@ test "long double" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_2_bool() @Vector(2, bool) { @@ -474,7 +477,13 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void; extern fn c_test_vector_2_bool() void; test "@Vector(2, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_2_bool(); try expect(vec[0] == true); @@ -488,8 +497,11 @@ test "@Vector(2, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_4_bool() @Vector(4, bool) { @@ -515,7 +527,13 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void; extern fn c_test_vector_4_bool() void; test "@Vector(4, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_4_bool(); try expect(vec[0] == true); @@ -533,8 +551,11 @@ test "@Vector(4, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_8_bool() @Vector(8, bool) { @@ -568,7 +589,13 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void; extern fn c_test_vector_8_bool() void; test "@Vector(8, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_8_bool(); try expect(vec[0] == false); @@ -594,8 +621,11 @@ test "@Vector(8, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_16_bool() @Vector(16, bool) { @@ -645,7 +675,13 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void; extern fn c_test_vector_16_bool() void; test "@Vector(16, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_16_bool(); try expect(vec[0] == true); @@ -687,8 +723,11 @@ test "@Vector(16, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_32_bool() @Vector(32, bool) { @@ -770,7 +809,13 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void; extern fn c_test_vector_32_bool() void; test "@Vector(32, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_32_bool(); try expect(vec[0] == true); @@ -844,8 +889,11 @@ test "@Vector(32, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_64_bool() @Vector(64, bool) { @@ -991,7 +1039,11 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void; extern fn c_test_vector_64_bool() void; test "@Vector(64, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const vec = c_ret_vector_64_bool(); try expect(vec[0] == false); @@ -1129,8 +1181,11 @@ test "@Vector(64, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_128_bool() @Vector(128, bool) { @@ -1404,7 +1459,11 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void; extern fn c_test_vector_128_bool() void; test "@Vector(128, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_128_bool(); try expect(vec[0] == false); @@ -1670,8 +1729,11 @@ test "@Vector(128, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_256_bool() @Vector(256, bool) { @@ -2201,7 +2263,11 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void; extern fn c_test_vector_256_bool() void; test "@Vector(256, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_256_bool(); try expect(vec[0] == true); @@ -2723,8 +2789,11 @@ test "@Vector(256, bool)" { comptime { skip: { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .hexagon) break :skip; + if (builtin.cpu.arch == .loongarch64) break :skip; + if (builtin.cpu.arch.isMIPS()) break :skip; + if (builtin.cpu.arch.isPowerPC64()) break :skip; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; _ = struct { export fn zig_ret_vector_512_bool() @Vector(512, bool) { @@ -3766,7 +3835,11 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void; extern fn c_test_vector_512_bool() void; test "@Vector(512, bool)" { - if (builtin.zig_backend == .stage2_llvm and (builtin.cpu.arch != .powerpc and builtin.cpu.arch != .wasm32)) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const vec = c_ret_vector_512_bool(); try expect(vec[0] == false); @@ -4840,7 +4913,7 @@ test "@Vector(2, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_2_u8(); try expect(v[0] == 9); @@ -4869,7 +4942,6 @@ test "@Vector(3, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_3_u8(); try expect(v[0] == 19); @@ -4912,7 +4984,7 @@ test "@Vector(4, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_4_u8(); try expect(v[0] == 41); @@ -4946,7 +5018,6 @@ test "@Vector(6, u8)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_6_u8(); try expect(v[0] == 53); @@ -9063,7 +9134,7 @@ test "@Vector(2, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; const v = c_ret_vector_2_u16(); try expect(v[0] == 9); @@ -9091,7 +9162,6 @@ test "@Vector(3, u16)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_3_u16(); try expect(v[0] == 19); @@ -12564,8 +12634,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void; extern fn c_test_vector_1_u64() void; test "@Vector(1, u64)" { - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; - const v = c_ret_vector_1_u64(); try expect(v[0] == 3); c_vector_1_u64(.{4}, 1); @@ -13291,7 +13359,6 @@ test "@Vector(1, f32)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag != .windows) return error.SkipZigTest; const v = c_ret_vector_1_f32(); try expect(v[0] == 3); @@ -14633,7 +14700,6 @@ test "@Vector(4, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_4_f64(); try expect(v[0] == 33); @@ -14701,7 +14767,6 @@ test "@Vector(8, f64)" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35899 const v = c_ret_vector_8_f64(); try expect(v[0] == 81); diff --git a/test/tests.zig b/test/tests.zig index 849267617f0cfe5e8c8f227a3758a397ba047083..d823d2add16c8a4486decb3671025cd60cbc16e2 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2015,7 +2015,6 @@ const c_abi_targets = blk: { .abi = .musl, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2026,7 +2025,6 @@ const c_abi_targets = blk: { }, .use_llvm = false, .strip = true, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2037,7 +2035,6 @@ const c_abi_targets = blk: { }, .use_llvm = false, .pic = true, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2082,7 +2079,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2092,7 +2088,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ @@ -2102,7 +2097,6 @@ const c_abi_targets = blk: { .abi = .gnu, }, .use_llvm = false, - .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ .target = .{ -- 2.54.0 From 6aed49f6baad85fc4a509f4c631da8c623e7c28f Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 15 Jul 2026 08:44:30 -0400 Subject: [PATCH 054/215] llvm.Builder: parse llvm alignment information from data layout This is required to correctly lower types in the llvm backend. --- lib/std/zig/llvm/Builder.zig | 563 ++++++++++++++++++++++++++++++++++- src/codegen/llvm.zig | 270 ++++------------- src/codegen/llvm/FuncGen.zig | 21 +- 3 files changed, 618 insertions(+), 236 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index a19a54651db7736b3a31ca926c534690ee27bf79..8b9e87f8139f951b7abc475c5afb3035176cb209 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -17,7 +17,7 @@ gpa: Allocator, strip: bool, source_filename: String, -data_layout: String, +data_layout: DataLayout, target_triple: String, module_asm: std.ArrayList(u8), @@ -87,6 +87,455 @@ pub const Options = struct { triple: []const u8 = &.{}, }; +pub const DataLayout = struct { + endian: ?std.lang.Endian, + int_specs: PrimitiveSpec.Map, + float_specs: PrimitiveSpec.Map, + vector_specs: PrimitiveSpec.Map, + pointer_specs: PointerSpec.Map, + string_repr: String, + + const PrimitiveSpec = packed struct(u32) { + bit_width: BitWidth, + abi_align: Alignment, + pref_align: Alignment, + + const BitWidth = u20; + + const Map = std.array_hash_map.Custom(PrimitiveSpec, void, Context, false); + + const Context = struct { + pub fn hash(_: Context, spec: PrimitiveSpec) u32 { + return std.hash.int(spec.bit_width); + } + + pub fn eql(_: Context, lhs_spec: PrimitiveSpec, rhs_spec: PrimitiveSpec, _: usize) bool { + return lhs_spec.bit_width == rhs_spec.bit_width; + } + }; + }; + + const PointerSpec = struct { + bit_width: BitWidth, + index_bit_width: BitWidth, + flags: packed struct(u32) { + abi_align: Alignment, + pref_align: Alignment, + has_unstable_repr: bool, + has_external_state: bool, + null_ptr_repr: NullPtrRepr, + unused: u17 = 0, + }, + addr_space_name: String, + + const BitWidth = u32; + + const NullPtrRepr = enum(u1) { all_zeros, all_ones }; + + const Map = std.array_hash_map.Auto(AddrSpace, PointerSpec); + }; + + pub fn stringForTarget(target: *const std.Target) []const u8 { + // These data layouts should match Clang. + return switch (target.cpu.arch) { + .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32", + .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32", + .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", + .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64", + .aarch64 => if (target.ofmt == .macho) + if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else if (target.abi == .ilp32) + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" + else if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" + else + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", + .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", + .arm => if (target.ofmt == .macho) + "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .armeb, .thumbeb => if (target.ofmt == .macho) + "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .thumb => if (target.ofmt == .macho) + "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else if (target.os.tag == .windows or target.os.tag == .uefi) + "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + else + "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8", + .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16", + .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + .mips64 => switch (target.abi) { + .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + }, + .mips64el => switch (target.abi) { + .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + }, + .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16", + .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32", + .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32", + .powerpc64 => switch (target.os.tag) { + .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", + .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64", + else => "E-m:e-Fn32-i64:64-i128:128-n32:64", + }, + .powerpc64le => if (target.os.tag == .linux) + "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512" + else + "e-m:e-Fn32-i64:64-i128:128-n32:64", + .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", + .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", + .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9", + .riscv32 => if (target.cpu.has(.riscv, .e)) + "e-m:e-p:32:32-i64:64-n32-S32" + else + "e-m:e-p:32:32-i64:64-n32-S128", + .riscv32be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:32:32-i64:64-n32-S32" + else + "E-m:e-p:32:32-i64:64-n32-S128", + .riscv64 => if (target.cpu.has(.riscv, .e)) + "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64" + else + "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .riscv64be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64" + else + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64", + .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128", + .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64", + .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) { + .gnu => if (target.ofmt == .coff) + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32", + else => blk: { + const msvc = switch (target.abi) { + .none, .msvc => true, + else => false, + }; + + break :blk if (target.ofmt == .coff) + if (msvc) + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" + else + "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" + else if (msvc) + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"; + }, + } else if (target.ofmt == .macho) + "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" + else + "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", + .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho) + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + else switch (target.abi) { + .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff) + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + else + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + }, + .spirv32 => switch (target.os.tag) { + .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + }, + .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", + .wasm32 => if (target.os.tag == .emscripten) + "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" + else + "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", + .wasm64 => if (target.os.tag == .emscripten) + "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" + else + "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", + .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64", + .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32", + .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128", + .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", + + .alpha, + .arceb, + .ez80, + .hppa, + .hppa64, + .kalimba, + .kvx, + .m88k, + .microblaze, + .microblazeel, + .or1k, + .propeller, + .sh, + .sheb, + .x86_16, + .xtensaeb, + => unreachable, + }; + } + + const default_int_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 8, .abi_align = .fromByteUnits(1), .pref_align = .fromByteUnits(1) }, // i8:8:8 + .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // i16:16:16 + .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // i32:32:32 + .{ .bit_width = 64, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(8) }, // i64:32:64 + }; + const default_float_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 16, .abi_align = .fromByteUnits(2), .pref_align = .fromByteUnits(2) }, // f16:16:16 + .{ .bit_width = 32, .abi_align = .fromByteUnits(4), .pref_align = .fromByteUnits(4) }, // f32:32:32 + .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // f64:64:64 + .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // f128:128:128 + }; + const default_vector_specs: []const PrimitiveSpec = &.{ + .{ .bit_width = 64, .abi_align = .fromByteUnits(8), .pref_align = .fromByteUnits(8) }, // v64:64:64 + .{ .bit_width = 128, .abi_align = .fromByteUnits(16), .pref_align = .fromByteUnits(16) }, // v128:128:128 + }; + + pub fn parseString(string_repr: String, builder: *Builder) Allocator.Error!DataLayout { + const gpa = builder.gpa; + + var int_specs: PrimitiveSpec.Map = .empty; + defer int_specs.deinit(gpa); + var float_specs: PrimitiveSpec.Map = .empty; + defer float_specs.deinit(gpa); + var vector_specs: PrimitiveSpec.Map = .empty; + defer vector_specs.deinit(gpa); + var pointer_specs: PointerSpec.Map = .empty; + defer pointer_specs.deinit(gpa); + var non_integral_addr_spaces: std.ArrayList(AddrSpace) = .empty; + defer non_integral_addr_spaces.deinit(gpa); + + try int_specs.ensureTotalCapacity(gpa, default_int_specs.len); + for (default_int_specs) |int_spec| int_specs.putAssumeCapacityNoClobber(int_spec, {}); + try float_specs.ensureTotalCapacity(gpa, default_float_specs.len); + for (default_float_specs) |float_spec| float_specs.putAssumeCapacityNoClobber(float_spec, {}); + try vector_specs.ensureTotalCapacity(gpa, default_vector_specs.len); + for (default_vector_specs) |vector_spec| vector_specs.putAssumeCapacityNoClobber(vector_spec, {}); + try pointer_specs.putNoClobber(gpa, .default, comptime .{ + .bit_width = 64, + .index_bit_width = 64, + .flags = .{ + .abi_align = .fromByteUnits(8), + .pref_align = .fromByteUnits(8), + .has_unstable_repr = false, + .has_external_state = false, + .null_ptr_repr = .all_zeros, + }, + .addr_space_name = .none, + }); + + var endian: ?std.lang.Endian = null; + var spec_it = std.mem.splitScalar(u8, string_repr.slice(builder).?, '-'); + while (spec_it.next()) |spec| switch (spec[0]) { + else => {}, + 'E' => { + assert(spec.len == 1); + assert(endian == null); + endian = .big; + }, + 'e' => { + assert(spec.len == 1); + assert(endian == null); + endian = .little; + }, + 'p' => { + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + + const first = field_it.first(); + var has_unstable_repr = false; + var has_external_state = false; + var null_ptr_repr: ?PointerSpec.NullPtrRepr = null; + var addr_space_name: String = .none; + const addr_space = for (first, 0..) |flag, as_start| switch (flag) { + 'u' => has_unstable_repr = true, + 'e' => has_external_state = true, + 'z' => { + assert(null_ptr_repr == null); + null_ptr_repr = .all_zeros; + }, + 'o' => { + assert(null_ptr_repr == null); + null_ptr_repr = .all_ones; + }, + else => { + if (first[first.len - ")".len] != ')') break first[as_start..]; + const name_start = std.mem.findScalarPos(u8, first, as_start, '(').?; + addr_space_name = try builder.string(first[name_start + "(".len .. first.len - ")".len]); + break first[as_start..name_start]; + }, + } else first[first.len..]; + const bit_width = std.fmt.parseInt(PointerSpec.BitWidth, field_it.next().?, 10) catch unreachable; + const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); + const pref_align: Alignment = if (field_it.next()) |pref_align| + .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) + else + abi_align; + const index_bit_width = if (field_it.next()) |index_bit_width| + std.fmt.parseInt(PointerSpec.BitWidth, index_bit_width, 10) catch unreachable + else + bit_width; + assert(field_it.peek() == null); + + try pointer_specs.put(gpa, switch (addr_space.len) { + 0 => .default, + else => @fromBackingInt(std.fmt.parseInt(u24, addr_space, 10) catch unreachable), + }, .{ + .bit_width = bit_width, + .index_bit_width = index_bit_width, + .flags = .{ + .abi_align = abi_align, + .pref_align = pref_align, + .has_unstable_repr = has_unstable_repr, + .has_external_state = has_external_state, + .null_ptr_repr = null_ptr_repr orelse .all_zeros, + }, + .addr_space_name = addr_space_name, + }); + }, + 'i', 'f', 'v' => |kind| { + if (std.mem.eql(u8, spec, "ve")) { + vector_specs.clearRetainingCapacity(); + continue; + } + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + const bit_width = std.fmt.parseInt(PrimitiveSpec.BitWidth, field_it.first(), 10) catch unreachable; + const abi_align: Alignment = .fromByteUnits(std.fmt.parseInt(u64, field_it.next().?, 10) catch unreachable); + const pref_align: Alignment = if (field_it.next()) |pref_align| + .fromByteUnits(std.fmt.parseInt(u64, pref_align, 10) catch unreachable) + else + abi_align; + assert(field_it.peek() == null); + const specs = switch (kind) { + else => unreachable, + 'i' => &int_specs, + 'f' => &float_specs, + 'v' => &vector_specs, + }; + try specs.put(gpa, .{ .bit_width = bit_width, .abi_align = abi_align, .pref_align = pref_align }, {}); + }, + 'n' => { + var field_it = std.mem.splitScalar(u8, spec[1..], ':'); + if (std.mem.eql(u8, field_it.first(), "i")) { + while (field_it.next()) |non_integral_addr_space| try non_integral_addr_spaces.append( + gpa, + @fromBackingInt(std.fmt.parseInt(u24, non_integral_addr_space, 10) catch unreachable), + ); + } else { + field_it.reset(); + while (field_it.next()) |native_bit_width| { + _ = std.fmt.parseInt(PrimitiveSpec.BitWidth, native_bit_width, 10) catch unreachable; + } + } + }, + }; + + for (non_integral_addr_spaces.items) |non_integral_addr_space| { + const pointer_spec_gop = try pointer_specs.getOrPut(gpa, non_integral_addr_space); + if (!pointer_spec_gop.found_existing) pointer_spec_gop.value_ptr.* = pointer_specs.get(.default).?; + pointer_spec_gop.value_ptr.flags.has_unstable_repr = true; + pointer_spec_gop.value_ptr.flags.has_external_state = false; + } + + { + const SortContext = struct { + specs: []const PrimitiveSpec, + pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { + return ctx.specs[lhs_index].bit_width < ctx.specs[rhs_index].bit_width; + } + }; + int_specs.sortUnstable(SortContext{ .specs = int_specs.keys() }); + float_specs.sortUnstable(SortContext{ .specs = float_specs.keys() }); + vector_specs.sortUnstable(SortContext{ .specs = vector_specs.keys() }); + } + { + const SortContext = struct { + addr_spaces: []const AddrSpace, + pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { + return @backingInt(ctx.addr_spaces[lhs_index]) < @backingInt(ctx.addr_spaces[rhs_index]); + } + }; + pointer_specs.sortUnstable(SortContext{ .addr_spaces = pointer_specs.keys() }); + assert(pointer_specs.keys()[0] == .default); + } + + return .{ + .endian = endian, + .int_specs = int_specs.move(), + .float_specs = float_specs.move(), + .vector_specs = vector_specs.move(), + .pointer_specs = pointer_specs.move(), + .string_repr = string_repr, + }; + } + + pub fn deinit(data_layout: *DataLayout, gpa: Allocator) void { + data_layout.int_specs.deinit(gpa); + data_layout.float_specs.deinit(gpa); + data_layout.vector_specs.deinit(gpa); + data_layout.pointer_specs.deinit(gpa); + } + + pub fn getIntegerSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { + const specs = data_layout.int_specs.keys(); + return specs[ + @min(std.sort.lowerBound(PrimitiveSpec, specs, bit_width, struct { + fn order(ctx: PrimitiveSpec.BitWidth, spec: PrimitiveSpec) std.math.Order { + return std.math.order(ctx, spec.bit_width); + } + }.order), specs.len - 1) + ]; + } + + pub fn getFloatSpec(data_layout: *const DataLayout, bit_width: PrimitiveSpec.BitWidth) PrimitiveSpec { + if (data_layout.float_specs.getEntry(.{ + .bit_width = bit_width, + .abi_align = .default, + .pref_align = .default, + })) |entry| return entry.key_ptr.*; + const default_align: Alignment = .fromByteUnits( + std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, bit_width / 8), + ); + return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; + } + + pub fn getVectorSpec( + data_layout: *const DataLayout, + bit_width: PrimitiveSpec.BitWidth, + store_size: Type.Size, + ) PrimitiveSpec { + if (data_layout.float_specs.getEntry(.{ + .bit_width = bit_width, + .abi_align = .default, + .pref_align = .default, + })) |entry| return entry.key_ptr.*; + const default_align: Alignment = .fromByteUnits( + std.math.ceilPowerOfTwoAssert(PrimitiveSpec.BitWidth, switch (store_size) { + .fixed, .scalable => |known_min| known_min, + }), + ); + return .{ .bit_width = bit_width, .abi_align = default_align, .pref_align = default_align }; + } + + pub fn getPointerSpec(data_layout: *const DataLayout, addr_space: AddrSpace) PointerSpec { + return data_layout.pointer_specs.get(addr_space) orelse data_layout.pointer_specs.values()[0]; + } +}; + pub const String = enum(u32) { none = maxInt(u31), empty, @@ -489,7 +938,10 @@ pub const Type = enum(u32) { .double, .i64, .x86_mmx => 64, .x86_fp80, .i80 => 80, .fp128, .ppc_fp128, .i128 => 128, - .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"), + .ptr => @intCast(builder.data_layout.getPointerSpec(.default).bit_width), + .@"ptr addrspace(4)" => @intCast( + builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(4))).bit_width, + ), _ => { const item = builder.type_items.items[@backingInt(self)]; return switch (item.tag) { @@ -498,7 +950,9 @@ pub const Type = enum(u32) { .vararg_function, => unreachable, .integer => @intCast(item.data), - .pointer => @panic("TODO: query data layout"), + .pointer => @intCast( + builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, + ), .target => unreachable, .vector, .scalable_vector, @@ -931,6 +1385,67 @@ pub const Type = enum(u32) { }, }; } + + const Size = union(enum) { fixed: u64, scalable: u64 }; + pub fn bits(ty: Type, builder: *const Builder) Size { + const item = builder.type_items.items[@backingInt(ty)]; + return switch (item.tag) { + else => unreachable, + .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) { + else => unreachable, + .label => .{ .fixed = builder.data_layout.getPointerSpec(.default).bit_width }, + .half, .bfloat => .{ .fixed = 16 }, + .float => .{ .fixed = 32 }, + .double => .{ .fixed = 64 }, + .ppc_fp128, .fp128 => .{ .fixed = 128 }, + .x86_amx => .{ .fixed = 8192 }, + .x86_fp80 => .{ .fixed = 80 }, + }, + .integer => .{ .fixed = item.data }, + .pointer => .{ + .fixed = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))).bit_width, + }, + }; + } + + pub fn alignment(ty: Type, kind: enum { abi, pref }, builder: *const Builder) Alignment { + const item = builder.type_items.items[@backingInt(ty)]; + switch (item.tag) { + else => unreachable, + .simple => switch (@as(Simple, @fromBackingInt(@intCast(item.data)))) { + else => unreachable, + .label => { + const spec = builder.data_layout.getPointerSpec(.default); + return switch (kind) { + .abi => spec.flags.abi_align, + .pref => spec.flags.pref_align, + }; + }, + .half, .bfloat, .float, .double, .ppc_fp128, .fp128, .x86_fp80 => { + const spec = builder.data_layout.getFloatSpec(@intCast(ty.bits(builder).fixed)); + return switch (kind) { + .abi => spec.abi_align, + .pref => spec.pref_align, + }; + }, + .x86_amx => return comptime .fromByteUnits(64), + }, + .integer => { + const spec = builder.data_layout.getIntegerSpec(@intCast(item.data)); + return switch (kind) { + .abi => spec.abi_align, + .pref => spec.pref_align, + }; + }, + .pointer => { + const spec = builder.data_layout.getPointerSpec(@fromBackingInt(@intCast(item.data))); + return switch (kind) { + .abi => spec.flags.abi_align, + .pref => spec.flags.pref_align, + }; + }, + } + } }; pub const Attribute = union(Kind) { @@ -2182,11 +2697,18 @@ pub const Alignment = enum(u6) { }; } - /// Asserts that neither `a` nor `b` is `.default`. - pub fn max(a: Alignment, b: Alignment) Alignment { - assert(a != .default); - assert(b != .default); - return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b)))); + /// Asserts that neither `lhs` nor `rhs` is `.default`. + pub fn max(lhs: Alignment, rhs: Alignment) Alignment { + assert(lhs != .default); + assert(rhs != .default); + return @fromBackingInt(@max(@backingInt(lhs), @backingInt(rhs))); + } + + /// Asserts that neither `lhs` nor `rhs` is `.default`. + pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order { + assert(lhs != .default); + assert(rhs != .default); + return std.math.order(@backingInt(lhs), @backingInt(rhs)); } pub fn toLlvm(self: Alignment) u6 { @@ -9023,7 +9545,14 @@ pub fn init(options: Options) Allocator.Error!Builder { .strip = options.strip, .source_filename = .none, - .data_layout = .none, + .data_layout = .{ + .endian = null, + .int_specs = .empty, + .float_specs = .empty, + .vector_specs = .empty, + .pointer_specs = .empty, + .string_repr = .none, + }, .target_triple = .none, .module_asm = .empty, @@ -9079,14 +9608,14 @@ pub fn init(options: Options) Allocator.Error!Builder { try self.string_indices.append(self.gpa, 0); assert(try self.string("") == .empty); + self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self); + try self.strtab_string_indices.append(self.gpa, 0); assert(try self.strtabString("") == .empty); if (options.name.len > 0) self.source_filename = try self.string(options.name); - if (options.triple.len > 0) { - self.target_triple = try self.string(options.triple); - } + if (options.triple.len > 0) self.target_triple = try self.string(options.triple); { const static_len = @typeInfo(Type).@"enum".field_names.len - 1; @@ -9179,6 +9708,8 @@ pub fn clearAndFree(self: *Builder) void { pub fn deinit(self: *Builder) void { const gpa = self.gpa; + self.data_layout.deinit(gpa); + self.module_asm.deinit(gpa); self.string_map.deinit(gpa); @@ -9998,17 +10529,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined }; defer metadata_formatter.map.deinit(self.gpa); - if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) { + if (self.source_filename != .none or self.data_layout.string_repr != .none or self.target_triple != .none) { if (need_newline) try w.writeByte('\n') else need_newline = true; if (self.source_filename != .none) try w.print( \\; ModuleID = '{s}' \\source_filename = {f} \\ , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) }); - if (self.data_layout != .none) try w.print( + if (self.data_layout.string_repr != .none) try w.print( \\target datalayout = {f} \\ - , .{self.data_layout.fmtQ(self)}); + , .{self.data_layout.string_repr.fmtQ(self)}); if (self.target_triple != .none) try w.print( \\target triple = {f} \\ @@ -13706,7 +14237,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }); } - if (self.data_layout.slice(self)) |data_layout| { + if (self.data_layout.string_repr.slice(self)) |data_layout| { try module_block.writeAbbrev(ModuleBlock.String{ .code = 3, .string = data_layout, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 221c9423e3a035367c010f0d6225940ab70a8ffb..689a0349ce7cf9aa2c49c2101f476303667c50cd 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool { }; } -pub fn dataLayout(target: *const std.Target) []const u8 { - // These data layouts should match Clang. - return switch (target.cpu.arch) { - .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32", - .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32", - .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", - .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64", - .aarch64 => if (target.ofmt == .macho) - if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else if (target.abi == .ilp32) - "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" - else if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32" - else - "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", - .aarch64_be => "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", - .arm => if (target.ofmt == .macho) - "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .armeb, .thumbeb => if (target.ofmt == .macho) - "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .thumb => if (target.ofmt == .macho) - "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else if (target.os.tag == .windows or target.os.tag == .uefi) - "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" - else - "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8", - .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16", - .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", - .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", - .mips64 => switch (target.abi) { - .gnuabin32, .muslabin32, .abin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - else => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - }, - .mips64el => switch (target.abi) { - .gnuabin32, .muslabin32, .abin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - else => "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", - }, - .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16", - .powerpc => "E-m:e-p:32:32-Fn32-i64:64-n32", - .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32", - .powerpc64 => switch (target.os.tag) { - .linux => "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512", - .ps3 => "E-m:e-p:32:32-Fi64-i64:64-i128:128-n32:64", - else => "E-m:e-Fn32-i64:64-i128:128-n32:64", - }, - .powerpc64le => if (target.os.tag == .linux) - "e-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512" - else - "e-m:e-Fn32-i64:64-i128:128-n32:64", - .nvptx => "e-p:32:32-p6:32:32-p7:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", - .nvptx64 => "e-p6:32:32-i64:64-i128:128-i256:256-v16:16-v32:32-n16:32:64", - .amdgcn => "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9", - .riscv32 => if (target.cpu.has(.riscv, .e)) - "e-m:e-p:32:32-i64:64-n32-S32" - else - "e-m:e-p:32:32-i64:64-n32-S128", - .riscv32be => if (target.cpu.has(.riscv, .e)) - "E-m:e-p:32:32-i64:64-n32-S32" - else - "E-m:e-p:32:32-i64:64-n32-S128", - .riscv64 => if (target.cpu.has(.riscv, .e)) - "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64" - else - "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .riscv64be => if (target.cpu.has(.riscv, .e)) - "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64" - else - "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64", - .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128", - .s390x => "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64", - .x86 => if (target.os.tag == .windows or target.os.tag == .uefi) switch (target.abi) { - .gnu => if (target.ofmt == .coff) - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32", - else => blk: { - const msvc = switch (target.abi) { - .none, .msvc => true, - else => false, - }; - - break :blk if (target.ofmt == .coff) - if (msvc) - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" - else - "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" - else if (msvc) - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"; - }, - } else if (target.ofmt == .macho) - "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" - else - "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", - .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho) - "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" - else switch (target.abi) { - .gnux32, .muslx32, .x32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - else => if ((target.os.tag == .windows or target.os.tag == .uefi) and target.ofmt == .coff) - "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" - else - "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - }, - .spirv32 => switch (target.os.tag) { - .vulkan, .opengl => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - else => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - }, - .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1", - .wasm32 => if (target.os.tag == .emscripten) - "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" - else - "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", - .wasm64 => if (target.os.tag == .emscripten) - "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20" - else - "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20", - .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64", - .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32", - .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128", - .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", - .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32", - - .alpha, - .arceb, - .ez80, - .hppa, - .hppa64, - .kalimba, - .kvx, - .m88k, - .microblaze, - .microblazeel, - .or1k, - .propeller, - .sh, - .sheb, - .x86_16, - .xtensaeb, - => unreachable, // Gated by hasLlvmSupport(). - }; -} - // Avoid depending on `bindings.CodeModel` in the bitcode-only case. const CodeModel = enum { default, @@ -618,8 +464,6 @@ pub const Object = struct { }); errdefer builder.deinit(); - builder.data_layout = try builder.string(dataLayout(target)); - const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref = if (!builder.strip) debug_info: { // We fully resolve all paths at this point to avoid lack of @@ -2865,18 +2709,38 @@ pub const Object = struct { pub const TypeRepr = enum { /// The representation of the type when it is being manipulated as a value in a function. - /// e.g. Zig `u5` -> LLVM `i5` + /// e.g. Zig `u90` -> LLVM `i90` as_value, - /// The representation of the type when it is stored in memory. - /// e.g. Zig `u5` -> LLVM `i8` + /// The representation of the type when it is loaded from or stored to memory. + /// e.g. Zig `u90` -> LLVM `i96` + memory_access, + /// The representation of the type when it is in memory. + /// e.g. Zig `u90` -> LLVM `[12 x i8]` in_memory, }; + pub fn intType(o: *Object, bits: u16, repr: TypeRepr) Allocator.Error!Builder.Type { + switch (repr) { + .as_value => return o.builder.intType(bits), + .memory_access, .in_memory => {}, + } + const target = o.zcu.getTarget(); + const abi_size = std.zig.target.intByteSize(target, bits); + const llvm_bit_width = @as(u20, 8) * abi_size; + switch (repr) { + .as_value => unreachable, + .memory_access => {}, + .in_memory => { + const zig_align = std.zig.target.intAlignment(target, bits); + const llvm_align = o.builder.data_layout.getIntegerSpec(llvm_bit_width).abi_align; + if (zig_align < llvm_align.toByteUnits().?) return o.builder.arrayType(abi_size, .i8); + }, + } + return o.builder.intType(llvm_bit_width); + } + pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type { - return o.builder.intType(switch (repr) { - .as_value => o.zcu.errorSetBits(), - .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8), - }); + return o.intType(o.zcu.errorSetBits(), repr); } pub const SoftF80Layout = struct { @@ -3029,42 +2893,31 @@ pub const Object = struct { const target = zcu.getTarget(); const ip = &zcu.intern_pool; - if (repr == .as_value) { - assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory + switch (repr) { + .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory + .memory_access, .in_memory => {}, } return switch (t.toIntern()) { .u0_type => unreachable, // no runtime bits - inline .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u80_type, - .u128_type, - .i128_type, - => |tag| switch (repr) { - .as_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), - .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), - }, - .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), - inline .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - => |tag| try o.builder.intType(target.cTypeBitSize( - @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), - ).?), + .u1_type => try o.intType(1, repr), + .u8_type, .i8_type => try o.intType(8, repr), + .u16_type, .i16_type => try o.intType(16, repr), + .u29_type => try o.intType(29, repr), + .u32_type, .i32_type => try o.intType(32, repr), + .u64_type, .i64_type => try o.intType(64, repr), + .u80_type => try o.intType(80, repr), + .u128_type, .i128_type => try o.intType(128, repr), + .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr), + .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr), + .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr), + .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr), + .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr), + .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr), + .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr), + .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr), + .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr), + .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr), .c_longdouble_type, .f16_type, .f32_type, @@ -3168,10 +3021,7 @@ pub const Object = struct { .none, => unreachable, else => switch (ip.indexToKey(t.toIntern())) { - .int_type => |int_type| switch (repr) { - .as_value => try o.builder.intType(int_type.bits), - .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), - }, + .int_type => |int_type| o.intType(int_type.bits, repr), .ptr_type => |ptr_type| type: { const ptr_ty = try o.builder.ptrType( toLlvmAddressSpace(ptr_type.flags.address_space, target), @@ -3189,7 +3039,7 @@ pub const Object = struct { try o.lowerType(.fromInterned(array_type.child), repr), ), .vector_type => |vector_type| if (isByRef(t, zcu)) { - const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .in_memory); + const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr); return o.builder.arrayType(vector_type.len, child_llvm_ty); } else { const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value); @@ -3454,7 +3304,7 @@ pub const Object = struct { return ty; }, .opaque_type, .spirv_type => unreachable, // no runtime bits - .enum_type => try o.lowerType(t.backingIntType(zcu), repr), + .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr), .func_type => |func_type| { assert(t.fnHasRuntimeBits(zcu)); return o.lowerFnType(.fromIntern(func_type, ip)); @@ -3525,7 +3375,7 @@ pub const Object = struct { .no_bits => continue, .byval => { const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); - try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .as_value)); + try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); @@ -3548,7 +3398,7 @@ pub const Object = struct { }, .float_array => |count| { const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access); try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); }, .i32_array, .i64_array => |arr_len| { @@ -3620,7 +3470,12 @@ pub const Object = struct { var bigint_space: Value.BigIntSpace = undefined; const bigint = val.toBigInt(&bigint_space, zcu); const llvm_int_ty = try o.lowerType(ty, repr); - return o.builder.bigIntConst(llvm_int_ty, bigint); + if (llvm_int_ty.isInteger(&o.builder)) + return o.builder.bigIntConst(llvm_int_ty, bigint); + const buffer = try o.gpa.alloc(u8, llvm_int_ty.aggregateLen(&o.builder)); + defer o.gpa.free(buffer); + bigint.writeTwosComplement(buffer, target.cpu.arch.endian()); + return o.builder.stringConst(try o.builder.string(buffer)); }, .err => |err| { const int = zcu.intern_pool.getErrorValueIfExists(err.name).?; @@ -3814,7 +3669,7 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(elem, if (is_by_ref) .in_memory else .as_value); + result_val.* = try o.lowerValue(elem, if (is_by_ref) repr else .as_value); }, .repeated_elem => unreachable, } @@ -3826,7 +3681,7 @@ pub const Object = struct { .repeated_elem => |elem| if (is_by_ref) { const vals = try allocator.alloc(Builder.Constant, vector_type.len); defer allocator.free(vals); - @memset(vals, try o.lowerValue(elem, .in_memory)); + @memset(vals, try o.lowerValue(elem, repr)); return o.builder.arrayConst(vector_ty, vals); } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)), } @@ -4287,9 +4142,8 @@ pub const Object = struct { } errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" })); - const llvm_ty = try o.lowerType(uav_ty, .in_memory); const llvm_name = try o.builder.strtabStringFmt("__anon_{d}", .{@backingInt(uav_val)}); - const llvm_variable = try o.builder.addVariable(llvm_name, llvm_ty, llvm_addrspace); + const llvm_variable = try o.builder.addVariable(llvm_name, .void, llvm_addrspace); gop.value_ptr.* = llvm_variable; try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder); llvm_variable.setMutability(.constant, &o.builder); diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 5bdf5029d1b4a639c41652f0792d56aba08e927a..f9ba9ecbac5056091f6ff13721ada61080baf5e4 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -830,7 +830,7 @@ fn buildCall( const alignment = arg_ty.abiAlignment(zcu).toLlvm(); // We don't need to handle non-ABI-sized integer types in memory here since they are // never by-ref. - const llvm_arg_ty = try o.lowerType(arg_ty, .in_memory); + const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access); const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, ""); try llvm_args.append(fg.gpa, loaded); } else { @@ -893,7 +893,7 @@ fn buildCall( break :ptr ptr; } else arg_val; - const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .memory_access); const array_ty = try o.builder.arrayType(count, float_ty); const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); @@ -4967,10 +4967,7 @@ fn buildZigAlloca(fg: *FuncGen, ty: Type, @"align": InternPool.Alignment) Alloca .none => ty.abiAlignment(o.zcu), else => |a| a, }; - return fg.buildAlloca( - try o.lowerType(ty, .in_memory), - resolved_align.toLlvm(), - ); + return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm()); } /// Unlike `WipFunction.alloca`, this puts the alloca instruction at the top of the function. @@ -6657,10 +6654,10 @@ fn load( return result_ptr; } - const llvm_memory_ty = try o.lowerType(load_ty, .in_memory); + const llvm_access_ty = try o.lowerType(load_ty, .memory_access); const llvm_value_ty = try o.lowerType(load_ty, .as_value); - if (llvm_memory_ty != llvm_value_ty) { + if (llvm_access_ty != llvm_value_ty) { assert(load_ty.isAbiInt(zcu)); // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special // handling for these, as LLVM's documented semantics are a valid implementation of Zig's @@ -6674,7 +6671,7 @@ fn load( // // Therefore, we handle these memory accesses specially: in this case we will actually load // the next-largest "natural" integer type and then truncate to `load_ty`. - const loaded = try fg.wip.load(access_kind, llvm_memory_ty, ptr, llvm_ptr_align, ""); + const loaded = try fg.wip.load(access_kind, llvm_access_ty, ptr, llvm_ptr_align, ""); // For packed structs, current Zig semantics don't really allow us to make the padding bits // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is // implemented, but until then, do a normal trunc for packed types. @@ -6731,17 +6728,17 @@ fn store( assert(elem.typeOfWip(&fg.wip) == try o.lowerType(elem_ty, .as_value)); - const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory); + const llvm_access_ty = try o.lowerType(elem_ty, .memory_access); const llvm_value_ty = try o.lowerType(elem_ty, .as_value); - if (llvm_memory_ty != llvm_value_ty) { + if (llvm_access_ty != llvm_value_ty) { assert(elem_ty.isAbiInt(zcu)); // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see // the corresponding comment in `FuncGen.load` for more details. const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) { .unsigned => .zext, .signed => .sext, - }, elem, llvm_memory_ty, ""); + }, elem, llvm_access_ty, ""); _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align); return; } -- 2.54.0 From 092f019be98b9cba5ecdc9a2b1a14ba107479a41 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 27 Jun 2026 02:05:27 -0400 Subject: [PATCH 055/215] llvm: implement placeholder powerpc64le c abi logic This was honestly easier than disabling most of the tests. --- src/codegen/llvm/FuncGen.zig | 111 +++++++++++--------- test/behavior/vector.zig | 1 - test/c_abi/cfuncs.c | 14 +-- test/c_abi/main.zig | 198 ++++++++++++++++++----------------- 4 files changed, 172 insertions(+), 152 deletions(-) diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index f9ba9ecbac5056091f6ff13721ada61080baf5e4..30a188749337f24690130a4a36e9fbe7a4cb578b 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -6987,25 +6987,12 @@ const ParamTypeIterator = struct { .async => { @panic("TODO implement async function lowering in the LLVM backend"); }, - .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), - .x86_64_win => return it.next_x86_64_win(ty), - .x86_stdcall => { - it.zig_index += 1; - it.llvm_index += 1; - - if (isScalar(zcu, ty)) { - return .byval; - } else { - it.byval_attr = true; - return .byref; - } - }, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => { it.zig_index += 1; it.llvm_index += 1; switch (aarch64_c_abi.classifyType(ty, zcu)) { .memory => return .byref_mut, - .float_array => |len| return Lowering{ .float_array = len }, + .float_array => |len| return .{ .float_array = len }, .byval => return .byval, .integer => { it.types_buffer[0..1].* = .{.i64}; @@ -7013,7 +7000,7 @@ const ParamTypeIterator = struct { it.types_len = 1; return .multiple_llvm_types; }, - .double_integer => return Lowering{ .i64_array = 2 }, + .double_integer => return .{ .i64_array = 2 }, } }, .arm_aapcs, .arm_aapcs_vfp => { @@ -7025,8 +7012,8 @@ const ParamTypeIterator = struct { return .byref; }, .byval => return .byval, - .i32_array => |size| return Lowering{ .i32_array = size }, - .i64_array => |size| return Lowering{ .i64_array = size }, + .i32_array => |size| return .{ .i32_array = size }, + .i64_array => |size| return .{ .i64_array = size }, } }, .mips_o32 => { @@ -7038,9 +7025,19 @@ const ParamTypeIterator = struct { return .byref; }, .byval => return .byval, - .i32_array => |size| return Lowering{ .i32_array = size }, + .i32_array => |size| return .{ .i32_array = size }, } }, + .powerpc64_elf_v2 => { + it.zig_index += 1; + it.llvm_index += 1; + if (isByRef(ty, zcu)) return switch (ty.abiSize(zcu)) { + 1...8 => .abi_sized_int, + 9...64 => |abi_size| .{ .i64_array = @intCast(@divCeil(abi_size, 8)) }, + else => .byref, + }; + return .byval; // TODO + }, .riscv64_lp64, .riscv32_ilp32 => { it.zig_index += 1; it.llvm_index += 1; @@ -7048,7 +7045,7 @@ const ParamTypeIterator = struct { .memory => return .byref_mut, .byval => return .byval, .integer => return .abi_sized_int, - .double_integer => return Lowering{ .i64_array = 2 }, + .double_integer => return .{ .i64_array = 2 }, .fields => { it.types_len = 0; var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| @@ -7108,6 +7105,19 @@ const ParamTypeIterator = struct { return .byref; }, }, + .x86_stdcall => { + it.zig_index += 1; + it.llvm_index += 1; + + if (isScalar(zcu, ty)) { + return .byval; + } else { + it.byval_attr = true; + return .byref; + } + }, + .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), + .x86_64_win => return it.next_x86_64_win(ty), // TODO investigate other callconvs else => { it.zig_index += 1; @@ -7294,7 +7304,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A const zcu = o.zcu; ret_ty.assertHasLayout(zcu); if (!ret_ty.hasRuntimeBits(zcu)) return .void; - switch (cc) { + return switch (cc) { .@"inline" => unreachable, .auto => { // Match the c calling convention in some cases to avoid llvm bugs. @@ -7307,36 +7317,31 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A 33...64 => .{ .mem_cast = .double }, else => .by_val, }; - - if (isByRef(ret_ty, zcu)) return .sret; - return .by_val; + return if (isByRef(ret_ty, zcu)) .sret else .by_val; }, - .x86_64_sysv, .x86_64_x32 => return fnReturnStrat_x86_64_sysv(o, ret_ty), - .x86_64_win => return fnReturnStrat_x86_64_win(o, ret_ty), - .x86_stdcall => if (isScalar(zcu, ret_ty)) { - assert(!isByRef(ret_ty, zcu)); - return .by_val; - } else return .sret, - .x86_fastcall => return fnReturnStrat_x86_fastcall(o, zcu, ret_ty), - .x86_sysv, .x86_win => return if (isByRef(ret_ty, zcu)) .sret else .by_val, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) { - .memory => return .sret, - .float_array, .byval => return .forceByVal(o, ret_ty), - .integer => return .{ .mem_cast = .i64 }, - .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) }, + .memory => .sret, + .float_array, .byval => .forceByVal(o, ret_ty), + .integer => .{ .mem_cast = .i64 }, + .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) }, }, .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) { - .memory, .i64_array => return .sret, - .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret, - .byval => return .forceByVal(o, ret_ty), + .memory, .i64_array => .sret, + .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, + .byval => .forceByVal(o, ret_ty), }, .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { - .memory, .i32_array => return .sret, - .byval => return .forceByVal(o, ret_ty), + .memory, .i32_array => .sret, + .byval => .forceByVal(o, ret_ty), }, + .powerpc64_elf_v2 => if (isByRef(ret_ty, zcu)) switch (ret_ty.abiSize(zcu)) { + 1...8 => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, + 9...16 => .{ .mem_cast = try o.builder.structType(.normal, &.{ .i64, .i64 }) }, + else => .sret, + } else .by_val, // TODO .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) { - .memory => return .sret, - .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, + .memory => .sret, + .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, .double_integer => { const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) { .riscv64, .riscv64be => .i64, @@ -7345,7 +7350,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A }; return .{ .mem_cast = try o.builder.structType(.normal, &.{ integer, integer }) }; }, - .byval => return .forceByVal(o, ret_ty), + .byval => .forceByVal(o, ret_ty), .fields => { var types_len: usize = 0; var types: [8]Builder.Type = undefined; @@ -7358,7 +7363,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A return .{ .mem_cast = try o.builder.structType(.normal, types[0..types_len]) }; }, }, - .s390x_sysv, .s390x_sysv_vx => return switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { + .s390x_sysv, .s390x_sysv_vx => switch (s390x_c_abi.classifyType(ret_ty, .ret, zcu)) { .none => .void, .double_or_float, .vector, .simple => .by_val, .simple_aggregate => unreachable, @@ -7368,14 +7373,20 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { assert(!isByRef(ret_ty, zcu)); return .by_val; - } else { - return .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }; - }, - .indirect => return .sret, + } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }, + .indirect => .sret, }, + .x86_stdcall => if (isScalar(zcu, ret_ty)) { + assert(!isByRef(ret_ty, zcu)); + return .by_val; + } else .sret, + .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty), + .x86_sysv, .x86_win => if (isByRef(ret_ty, zcu)) .sret else .by_val, + .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty), + .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty), // TODO investigate other callconvs - else => return .forceByVal(o, ret_ty), - } + else => .forceByVal(o, ret_ty), + }; } fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 5838231e75ed214364a9a1af0527e5b9e480eaa9..861b2e77db418adbb23343bf0a90db3733ad82f6 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -736,7 +736,6 @@ test "vector reduce operation" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562 const S = struct { fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void { diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 101e07c97ccf7a4c9c2cd702c545b7898f858082..91a33b24ad4d3ffbefc648495d1291491827677c 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -77,7 +77,7 @@ static void assert_or_panic(bool ok) { # define ZIG_NO_COMPLEX #endif -#ifdef ZIG_PPC32 +#ifdef __powerpc__ # define ZIG_NO_COMPLEX #endif @@ -15571,7 +15571,7 @@ void run_c_tests(void) { #if !(defined(__i386__) && defined(_WIN32)) #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct Struct_i32_i32 s = {1, 2}; zig_struct_i32_i32(s); @@ -15584,7 +15584,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct BigStruct s = {1, 2, 3, 4, 5}; zig_big_struct(s); @@ -15616,7 +15616,7 @@ void run_c_tests(void) { #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct SplitStructInts s = {1234, 100, 1337}; zig_split_struct_ints(s); @@ -15630,7 +15630,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct MedStructMixed s = {1234, 100.0f, 1337.0f}; zig_med_struct_mixed(s); @@ -15644,7 +15644,7 @@ void run_c_tests(void) { #ifndef __i386__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct SplitStructMixed s = {1234, 100, 1337.0f}; zig_split_struct_mixed(s); @@ -15658,7 +15658,7 @@ void run_c_tests(void) { #ifndef __hexagon__ #ifndef __loongarch__ #ifndef ZIG_MIPS64 -#ifndef __powerpc__ +#ifndef ZIG_PPC32 { struct BigStruct s = {30, 31, 32, 33, 34}; struct BigStruct res = zig_big_struct_both(s); diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 1f9b5a9f2ab04f4d3269a1ff6058d1d15ae2a63c..f1bbd96806d3b507ee0448f4415f811aae2d929a 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -161,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat; extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble; const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and - !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and + !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and builtin.cpu.arch != .hexagon and builtin.cpu.arch != .s390x and !(builtin.cpu.arch.isLoongArch() and builtin.abi.float() == .soft); @@ -15384,7 +15384,7 @@ test "struct u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8(); @@ -15418,7 +15418,7 @@ test "struct u8, u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8(); @@ -15455,7 +15455,7 @@ test "struct u8, u8, u8, u8" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u8_u8_u8_u8(); @@ -15516,7 +15516,7 @@ test "struct u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = c_ret_struct_u16_u16(); @@ -15550,7 +15550,7 @@ test "struct u16, u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; @@ -15588,7 +15588,7 @@ test "struct u16, u16, u16, u16" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86) return error.SkipZigTest; @@ -15649,7 +15649,7 @@ extern fn c_test_struct_u32_u32() void; test "struct u32, u32" { if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -15684,7 +15684,7 @@ test "struct u32, u32, u32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32(); try expect(s.a == 8); @@ -15720,7 +15720,7 @@ test "struct u32, u32, u32, u32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_u32_u32_u32(); try expect(s.a == 10); @@ -15866,7 +15866,7 @@ extern fn c_test_struct_u64_u64_u64() void; test "struct u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64(); try expect(s.a == 8); @@ -15901,7 +15901,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void; test "struct u64, u64, u64, u64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u64_u64_u64_u64(); try expect(s.a == 10); @@ -15930,7 +15930,7 @@ extern fn c_test_struct_f32() void; test "struct f32" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s = c_ret_struct_f32(); @@ -16173,7 +16173,7 @@ test "struct {f32, f32}, f32" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f32f32_f32(); try expect(s.a.b == 1.0); @@ -16206,7 +16206,7 @@ test "struct f32, {f32, f32}" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f32_f32f32(); try expect(s.a == 1.0); @@ -16234,7 +16234,7 @@ extern fn c_test_struct_f64() void; test "struct f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -16265,7 +16265,7 @@ extern fn c_test_struct_f64_f64() void; test "struct f64, f64" { if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64(); try expect(s.a == 6); @@ -16297,7 +16297,7 @@ extern fn c_test_struct_f64_f64_f64() void; test "struct f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64(); try expect(s.a == 8); @@ -16332,7 +16332,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void; test "struct f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64(); try expect(s.a == 10); @@ -16370,7 +16370,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void; test "struct f64, f64, f64, f64, f64" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; const s = c_ret_struct_f64_f64_f64_f64_f64(); try expect(s.a == 12); @@ -16409,7 +16409,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" { if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = c_ret_struct_u32_union_u32_u32u32(); try expect(s.a == 1); @@ -16427,10 +16427,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32; extern fn c_struct_i32_i32(Struct_i32_i32) void; test "struct i32 i32" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const s: Struct_i32_i32 = .{ @@ -16460,10 +16460,10 @@ const BigStruct = extern struct { extern fn c_big_struct(BigStruct) void; test "big struct" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16489,9 +16489,9 @@ const BigUnion = extern union { extern fn c_big_union(BigUnion) void; test "big union" { - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -16523,10 +16523,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void; extern fn c_ret_med_struct_mixed() MedStructMixed; test "medium struct of ints and floats" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = MedStructMixed{ .a = 1234, @@ -16602,11 +16602,11 @@ const SplitStructInt = extern struct { extern fn c_split_struct_ints(SplitStructInt) void; test "split struct of ints" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = SplitStructInt{ .a = 1234, @@ -16631,11 +16631,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void; extern fn c_ret_split_struct_mixed() SplitStructMixed; test "split struct of ints and floats" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; const s = SplitStructMixed{ .a = 1234, @@ -16658,10 +16658,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void { extern fn c_big_struct_both(BigStruct) BigStruct; test "sret and byval together" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const s = BigStruct{ .a = 1, @@ -16771,11 +16771,11 @@ extern fn c_struct_with_array(StructWithArray) void; extern fn c_ret_struct_with_array() StructWithArray; test "Struct with array as padding." { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 }); @@ -16799,10 +16799,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void; extern fn c_ret_float_array_struct() FloatArrayStruct; test "Float array like struct" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; c_float_array_struct(.{ .origin = .{ @@ -16833,33 +16833,37 @@ pub inline fn expectOk(c_err: c_int) !void { /// Tests for Double + Char struct const DC = extern struct { v1: f64, v2: u8 }; test "DC: Zig passes to C" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 })); } test "DC: Zig returns to C" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectOk(c_assert_ret_DC()); } test "DC: C passes to Zig" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_send_DC()); } test "DC: C returns to Zig" { + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC()); } @@ -16884,32 +16888,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 }; test "CFF: Zig passes to C" { if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 })); } test "CFF: Zig returns to C" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + try expectOk(c_assert_ret_CFF()); } test "CFF: C passes to Zig" { - if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; - if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; + if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; try expectOk(c_send_CFF()); } test "CFF: C returns to Zig" { - if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV() and builtin.mode != .debug) return error.SkipZigTest; + try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF()); } pub extern fn c_assert_CFF(lv: CFF) c_int; @@ -16932,31 +16939,35 @@ pub export fn zig_ret_CFF() CFF { const PD = extern struct { v1: ?*anyopaque, v2: f64 }; test "PD: Zig passes to C" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; + try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 })); } test "PD: Zig returns to C" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + try expectOk(c_assert_ret_PD()); } test "PD: C passes to Zig" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; + try expectOk(c_send_PD()); } test "PD: C returns to Zig" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; + try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD()); } pub extern fn c_assert_PD(lv: PD) c_int; @@ -17010,10 +17021,10 @@ const ByVal = extern struct { extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void; test "C function that takes byval struct called via function pointer" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; var fn_ptr = &c_func_ptr_byval; _ = &fn_ptr; @@ -17032,17 +17043,16 @@ test "C function that takes byval struct called via function pointer" { extern fn c_f16(f16) f16; test "f16 bare" { - if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; - if (builtin.cpu.arch == .x86) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - - if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .x86) return error.SkipZigTest; + if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; const a = c_f16(12); try expect(a == 34); @@ -17053,9 +17063,9 @@ const f16_struct = extern struct { }; extern fn c_f16_struct(f16_struct) f16_struct; test "f16 struct" { + if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; @@ -17162,10 +17172,10 @@ const Coord2 = extern struct { extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2; test "Stdcall ABI structs" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; - if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; const res = stdcall_coord2( @@ -17179,9 +17189,9 @@ test "Stdcall ABI structs" { extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void; test "Stdcall ABI big union" { - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; const x = BigUnion{ .a = BigStruct{ @@ -17253,10 +17263,10 @@ const byval_tail_callsite_attr = struct { }; test "byval tail callsite attribute" { - if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; - if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // Originally reported at https://github.com/ziglang/zig/issues/16290 // the bug was that the extern function had the byval attribute, but -- 2.54.0 From 703baa4cd662e55ba39ea14ae2f30209e7ff023b Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 1 Jul 2026 12:01:07 -0400 Subject: [PATCH 056/215] llvm: implement c abi for loongarch Closes #35798 --- CMakeLists.txt | 1 + src/codegen/llvm/FuncGen.zig | 86 ++++++++++++++++++++++ src/codegen/loongarch/abi.zig | 133 ++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 src/codegen/loongarch/abi.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index ad4d8bea72ee199d041ef28559b536de2f20f7e3..14df4e9b568d8fb6c5b924f6cd4e3c9778dc5e21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,6 +358,7 @@ set(ZIG_STAGE2_SOURCES src/codegen/c/type/render_defs.zig src/codegen/llvm.zig src/codegen/llvm/bindings.zig + src/codegen/loongarch/abi.zig src/codegen/s390x/abi.zig src/crash_report.zig src/dev.zig diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 30a188749337f24690130a4a36e9fbe7a4cb578b..84a7af8362e91e54003cdf82378ce1037b2f617f 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -7016,6 +7016,71 @@ const ParamTypeIterator = struct { .i64_array => |size| return .{ .i64_array = size }, } }, + .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ty, zcu)) { + .ignored => { + it.zig_index += 1; + return .no_bits; + }, + .gar, .far => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + .member => |member_ty| { + it.types_buffer[0..1].* = .{ + try it.object.lowerType(member_ty, .as_value), + }; + it.offsets_buffer[0..2].* = .{ 0, member_ty.abiSize(zcu) }; + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + }, + .member_pair => |member_tys| { + it.types_buffer[0..2].* = .{ + try it.object.lowerType(member_tys[0], .as_value), + try it.object.lowerType(member_tys[1], .as_value), + }; + const first_size = member_tys[0].abiSize(zcu); + const second_size = member_tys[0].abiSize(zcu); + it.offsets_buffer[0..3].* = .{ 0, first_size, first_size + second_size }; + it.types_len = 2; + it.zig_index += 1; + it.llvm_index += 2; + return .multiple_llvm_types; + }, + .memory_gar => { + switch (it.cc) { + else => unreachable, + .loongarch32_ilp32 => { + it.types_buffer[0..1].* = .{.i32}; + it.offsets_buffer[0..2].* = .{ 0, 4 }; + }, + .loongarch64_lp64 => { + it.types_buffer[0..1].* = .{.i64}; + it.offsets_buffer[0..2].* = .{ 0, 8 }; + }, + } + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + }, + .memory_gar_pair => { + it.zig_index += 1; + it.llvm_index += 1; + return switch (it.cc) { + else => unreachable, + .loongarch32_ilp32 => .{ .i32_array = 2 }, + .loongarch64_lp64 => .{ .i64_array = 2 }, + }; + }, + .address => { + it.zig_index += 1; + it.llvm_index += 1; + return .byref; + }, + }, .mips_o32 => { it.zig_index += 1; it.llvm_index += 1; @@ -7330,6 +7395,26 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, .byval => .forceByVal(o, ret_ty), }, + .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) { + .ignored => .void, + .gar, .far => .by_val, + .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) }, + .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{ + try o.lowerType(member_tys[0], .as_value), + try o.lowerType(member_tys[1], .as_value), + }) }, + .memory_gar => .{ .mem_cast = switch (cc) { + else => unreachable, + .loongarch32_ilp32 => .i32, + .loongarch64_lp64 => .i64, + } }, + .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) { + else => unreachable, + .loongarch32_ilp32 => .i32, + .loongarch64_lp64 => .i64, + }) }, + .address => .sret, + }, .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { .memory, .i32_array => .sret, .byval => .forceByVal(o, ret_ty), @@ -8124,6 +8209,7 @@ const math = std.math; const aarch64_c_abi = @import("../aarch64/abi.zig"); const arm_c_abi = @import("../arm/abi.zig"); +const loongarch_c_abi = @import("../loongarch/abi.zig"); const mips_c_abi = @import("../mips/abi.zig"); const riscv_c_abi = @import("../riscv64/abi.zig"); const s390x_c_abi = @import("../s390x/abi.zig"); diff --git a/src/codegen/loongarch/abi.zig b/src/codegen/loongarch/abi.zig new file mode 100644 index 0000000000000000000000000000000000000000..09e42a7cb96731dbf0ee44b37ad74f0548a08c93 --- /dev/null +++ b/src/codegen/loongarch/abi.zig @@ -0,0 +1,133 @@ +const std = @import("std"); +const InternPool = @import("../../InternPool.zig"); +const Type = @import("../../Type.zig"); +const Zcu = @import("../../Zcu.zig"); + +pub const Class = union(enum) { + ignored, + gar, + far, + member: Type, + member_pair: [2]Type, + memory_gar, + memory_gar_pair, + address, + + fn combineMember(container_class: Class, member_class: Class, member_ty: Type) Class { + const second_member_ty = switch (member_class) { + .ignored => return container_class, + .gar, .far => member_ty, + .member => |second_member_ty| second_member_ty, + .member_pair, .memory_gar, .memory_gar_pair, .address => return .address, + }; + return switch (container_class) { + .ignored => .{ .member = second_member_ty }, + .gar, .far, .memory_gar, .memory_gar_pair => unreachable, + .member => |first_member_ty| .{ .member_pair = .{ first_member_ty, second_member_ty } }, + .member_pair, .address => .address, + }; + } +}; + +pub fn classifyType(ty: Type, zcu: *Zcu) Class { + return Classifier.init(zcu).classifyType(ty); +} + +const Classifier = struct { + zcu: *Zcu, + target: *const std.Target, + grlen: u8, + frlen: u8, + + fn init(zcu: *Zcu) Classifier { + const target = zcu.getTarget(); + return .{ + .zcu = zcu, + .target = target, + .grlen = switch (target.cpu.arch) { + else => unreachable, + .loongarch32 => 32, + .loongarch64 => 64, + }, + .frlen = if (target.cpu.has(.loongarch, .d)) + 64 + else if (target.cpu.has(.loongarch, .f)) + 32 + else + 0, + }; + } + + fn classifyType(c: Classifier, ty: Type) Class { + switch (ty.zigTypeTag(c.zcu)) { + .type, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_union, + .error_set, + .@"fn", + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + .spirv, + => unreachable, + .void, .noreturn => return .ignored, + .bool => return .gar, + .int, .@"enum" => { + const bits = ty.intInfo(c.zcu).bits; + if (bits == 0) return .ignored; + if (bits <= c.grlen) return .gar; + if (bits <= 2 * c.grlen) return .memory_gar_pair; + return .address; + }, + .float => { + const bits = ty.floatBits(c.target); + if (bits <= c.frlen) return .far; + if (bits <= c.grlen) return .gar; + if (bits <= 2 * c.grlen) return .memory_gar_pair; + return .address; + }, + .pointer, .optional => return .gar, + .array => { + var class: Class = .ignored; + const elem_ty = ty.childType(c.zcu); + const elem_class = c.classifyType(elem_ty); + for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| { + class = class.combineMember(elem_class, elem_ty); + if (class == .address) break; + } + if (class != .address) return class; + }, + .@"struct" => switch (ty.containerLayout(c.zcu)) { + .auto => unreachable, + .@"extern" => { + var class: Class = .ignored; + var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (c.zcu.typeToStruct(ty)) |loaded_struct| + loaded_struct.iterateRuntimeOrder(&c.zcu.intern_pool) + else + .{ .runtime_order = null, .fields_len = ty.structFieldCount(c.zcu), .next_index = 0 }; + while (field_it.next()) |field_index| { + const field_ty = ty.fieldType(field_index, c.zcu); + class = class.combineMember(c.classifyType(field_ty), field_ty); + if (class == .address) break; + } + if (class != .address) return class; + }, + .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), + }, + .@"union" => switch (ty.containerLayout(c.zcu)) { + .auto => unreachable, + .@"extern" => {}, + .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), + }, + .vector => {}, + } + const size = ty.abiSize(c.zcu); + if (size <= @divExact(c.grlen, 8)) return .memory_gar; + if (size <= @divExact(2 * c.grlen, 8)) return .memory_gar_pair; + return .address; + } +}; -- 2.54.0 From f2f770fdd3818d1ec14e51ce752aca5beb08e150 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sat, 4 Jul 2026 13:56:17 -0400 Subject: [PATCH 057/215] llvm: implement c abi for x86 --- lib/std/Target.zig | 9 +- lib/std/lang.zig | 1 + src/Sema.zig | 1 + src/Zcu.zig | 2 + src/codegen.zig | 195 +++++++++++++++++++++++++++++++++++ src/codegen/c.zig | 2 +- src/codegen/llvm.zig | 18 +++- src/codegen/llvm/FuncGen.zig | 117 +++++++++++++++++---- src/link/Dwarf.zig | 3 +- 9 files changed, 315 insertions(+), 33 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 3a6cfabb42be0d191520ef33ae7cbbc190e7c644..2f395dc0f03d6aa5673df31b4aa3bb92d66bf50a 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1797,6 +1797,7 @@ pub const Cpu = struct { .x86_sysv, .x86_win, + .x86_mingw, .x86_stdcall, .x86_fastcall, .x86_thiscall, @@ -3664,18 +3665,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention { return switch (target.cpu.arch) { .x86_64 => switch (target.os.tag) { - .windows, - .uefi, - => .{ .x86_64_win = .{} }, + .windows, .uefi => .{ .x86_64_win = .{} }, else => switch (target.abi) { .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} }, else => .{ .x86_64_sysv = .{} }, }, }, .x86 => switch (target.os.tag) { - .windows, - .uefi, - => .{ .x86_win = .{} }, + .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} }, else => .{ .x86_sysv = .{} }, }, .x86_16 => .{ .x86_16_cdecl = .{} }, diff --git a/lib/std/lang.zig b/lib/std/lang.zig index 2f0868c39331456b03f055cafd8546f19ac51b07..f15f26d9f9330431846e52ff9d98b131fbc666e2 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -214,6 +214,7 @@ pub const CallingConvention = union(enum(u8)) { // Calling conventions for the `x86` architecture. x86_sysv: X86RegparmOptions, x86_win: X86RegparmOptions, + x86_mingw: X86RegparmOptions, x86_stdcall: X86RegparmOptions, x86_fastcall: CommonOptions, x86_thiscall: CommonOptions, diff --git a/src/Sema.zig b/src/Sema.zig index cb8f87836a5e2c8623670cb870f7bf2b4b05a43d..2181fa563b9e9dec42b1123cc3b738874df64ca7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8501,6 +8501,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta .x86_64_win, .x86_sysv, .x86_win, + .x86_mingw, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win, diff --git a/src/Zcu.zig b/src/Zcu.zig index d71d8ecf80ef074a1800c9d637744a023523fede..2af36db254d2edbcfe3ae8a05de265b882d46b01 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4644,6 +4644,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_sysv, .x86_win, + .x86_mingw, .x86_stdcall, => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, @@ -4678,6 +4679,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .stage2_x86 => switch (cc) { .x86_sysv, .x86_win, + .x86_mingw, => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, .naked => true, else => false, diff --git a/src/codegen.zig b/src/codegen.zig index a691b36a4811f7cf127de20aa50d33e2b6e8d700..4ad10d48c05c59608f06956209f7f9b66a6d2775 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1124,6 +1124,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu: }; } +pub const FlattenedItem = struct { offset: u64, type: ?Type }; +pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct { + offset: u64 = 0, + allow_arrays: bool = true, + fn increaseOffset(opts: @This(), offset: u64) @This() { + return .{ + .offset = opts.offset + offset, + .allow_arrays = opts.allow_arrays, + }; + } +}) ?[]FlattenedItem { + const ip = &zcu.intern_pool; + switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| { + if (int_type.bits == 0) return items_buf[0..0]; + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .ptr_type => |ptr_type| switch (ptr_type.flags.size) { + .one, .many, .c => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .slice => { + if (items_buf.len < 2) return null; + const items = items_buf[0..2]; + const ptr_field_ty = ty.slicePtrFieldType(zcu); + items.* = .{ + .{ .offset = opts.offset, .type = ptr_field_ty }, + .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize }, + }; + return items; + }, + }, + .array_type => |array_type| { + const len = array_type.lenIncludingSentinel(); + if (len == 0) return items_buf[0..0]; + const elem_ty: Type = .fromInterned(array_type.child); + const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null; + if (elem_items.len == 0) return items_buf[0..0]; + if (!opts.allow_arrays) return null; + const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len); + if (items_overflow != 0 or items_buf.len < items_len) return null; + var items_index = elem_items.len; + const elem_size = elem_ty.abiSize(zcu); + var elem_offset: u64 = elem_size; + while (items_index != items_len) : ({ + items_index += elem_items.len; + elem_offset += elem_size; + }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| { + item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type }; + }; + return items_buf[0..@intCast(items_len)]; + }, + .vector_type => |vector_type| { + if (vector_type.len == 0) return items_buf[0..0]; + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .opt_type, .error_union_type => return null, + .simple_type => |simple_type| switch (simple_type) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .bool, + .anyerror, + => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .anyopaque, .noreturn => return null, + .void, + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, + .enum_literal, + => return items_buf[0..0], + .adhoc_inferred_error_set, .generic_poison => unreachable, + }, + .struct_type => { + const loaded_struct = ip.loadStructType(ty.toIntern()); + switch (loaded_struct.layout) { + .auto, .@"extern" => {}, + .@"packed" => return flattenType(items_buf, .fromInterned( + loaded_struct.packed_backing_int_type, + ), zcu, opts), + } + var items_len: usize = 0; + var offset: u64 = 0; + var field_it = loaded_struct.iterateRuntimeOrder(ip); + while (field_it.next()) |field_index| { + const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const field_offset = loaded_struct.field_offsets.get(ip)[field_index]; + if (field_offset - offset > 0 and + (items_len == 0 or items_buf[items_len - 1].type != null)) + { + if (items_len == items_buf.len) return null; + items_buf[items_len] = .{ .offset = offset, .type = null }; + items_len += 1; + } + items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( + field_offset, + )) orelse return null).len; + offset = field_offset + field_ty.abiSize(zcu); + } + if (ty.abiSize(zcu) - offset > 0 and + (items_len == 0 or items_buf[items_len - 1].type != null)) + { + if (items_len == items_buf.len) return null; + items_buf[items_len] = .{ .offset = offset, .type = null }; + items_len += 1; + } + return items_buf[0..items_len]; + }, + .tuple_type => |tuple_type| { + if (items_buf.len < tuple_type.types.len) return null; + var items_len: usize = 0; + var offset: u64 = 0; + for (tuple_type.types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + offset = field_ty.abiAlignment(zcu).forward(offset); + items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset( + offset, + )) orelse return null).len; + offset += field_ty.abiSize(zcu); + } + return items_buf[0..items_len]; + }, + .union_type => { + const loaded_union = ip.loadUnionType(ty.toIntern()); + return switch (loaded_union.layout) { + .auto, .@"extern" => return null, + .@"packed" => return flattenType(items_buf, .fromInterned( + loaded_union.packed_backing_int_type, + ), zcu, opts), + }; + }, + .opaque_type, .spirv_type, .func_type => return null, + .enum_type => return flattenType(items_buf, .fromInterned( + ip.loadEnumType(ty.toIntern()).int_tag_type, + ), zcu, opts), + .error_set_type, .inferred_error_set_type => { + if (items_buf.len < 1) return null; + const items = items_buf[0..1]; + items.* = .{.{ .offset = opts.offset, .type = ty }}; + return items; + }, + .anyframe_type, + // values, not types + .undef, + .simple_value, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + // memoization, not types + .memoized_call, + => unreachable, + } +} + test { _ = aarch64; } diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d1605b457e2f3673807c16fd10836612aae804d5..1633321426dfc3044177eebe0cd44e6fda3c6aa9 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -7289,7 +7289,7 @@ fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 { .x86_16_cdecl => "cdecl", .x86_16_regparmcall => "regparmcall", .x86_64_sysv, .x86_sysv => "sysv_abi", - .x86_64_win, .x86_win => "ms_abi", + .x86_64_win, .x86_win, .x86_mingw => "ms_abi", .x86_16_stdcall, .x86_stdcall => "stdcall", .x86_fastcall => "fastcall", .x86_thiscall => "thiscall", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 689a0349ce7cf9aa2c49c2101f476303667c50cd..de5f084008896d56c36ff371078b6581a306a45f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4235,19 +4235,26 @@ pub const Object = struct { }; } + pub const Byval = struct { alignment: InternPool.Alignment = .none }; pub fn addByRefParamAttrs( o: *Object, attributes: *Builder.FunctionAttributes.Wip, llvm_arg_i: u32, - byval: bool, + maybe_byval: ?Byval, param_ty: Type, ) Allocator.Error!void { const llvm_param_ty = try o.lowerType(param_ty, .in_memory); - const alignment = param_ty.abiAlignment(o.zcu).toLlvm(); - try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); - try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder); - if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); + try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); + try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); + const alignment = if (maybe_byval) |byval| alignment: { + try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); + break :alignment byval.alignment; + } else .none; + try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) { + .none => param_ty.abiAlignment(o.zcu), + else => alignment, + }.toLlvm()) }, &o.builder); } pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index { @@ -4598,6 +4605,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const .x86_16_interrupt, .x86_sysv, .x86_win, + .x86_mingw, .x86_thiscall_mingw, .x86_64_x32, .aarch64_aapcs, diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 84a7af8362e91e54003cdf82378ce1037b2f617f..1dfdfba987f0e962049294699bba1bcce3aac4bf 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { switch (lowering) { .no_bits => continue, .byval => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_index = it.zig_index - 1; const param_ty: Type = .fromInterned(param_types[param_index]); const param = fg.wip.arg(it.llvm_index - 1); @@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { .byref, .byref_mut => { const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param = fg.wip.arg(it.llvm_index - 1); + const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none; - if (isByRef(param_ty, zcu)) { + if (alignment == .none and isByRef(param_ty, zcu)) { args.appendAssumeCapacity(param); } else { - args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal)); + args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal)); } }, .abi_sized_int => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param = fg.wip.arg(it.llvm_index - 1); @@ -260,7 +261,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { } }, .slice => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); assert(!isByRef(param_ty, zcu)); const slice_val = try fg.wip.buildAggregate( @@ -271,7 +272,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { args.appendAssumeCapacity(slice_val); }, .multiple_llvm_types => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); const param_alignment = param_ty.abiAlignment(zcu); const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); @@ -963,7 +964,7 @@ fn buildCall( => continue, .slice => { - assert(!it.byval_attr); + assert(it.byval_attr == null); const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); const ptr_info = param_ty.ptrInfo(zcu); const llvm_arg_i = it.llvm_index - 2; @@ -6913,7 +6914,7 @@ const ParamTypeIterator = struct { types_len: u32, types_buffer: [8]Builder.Type, offsets_buffer: [9]u64, - byval_attr: bool, + byval_attr: ?Object.Byval, const Lowering = union(enum) { no_bits, @@ -6931,7 +6932,7 @@ const ParamTypeIterator = struct { pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { if (it.zig_index >= it.param_types.len) return null; const ty = it.param_types[it.zig_index]; - it.byval_attr = false; + it.byval_attr = null; return nextInner(it, Type.fromInterned(ty)); } @@ -7008,7 +7009,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; switch (arm_c_abi.classifyType(ty, zcu, .arg)) { .memory => { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .byval => return .byval, @@ -7086,7 +7087,7 @@ const ParamTypeIterator = struct { it.llvm_index += 1; switch (mips_c_abi.classifyType(ty, zcu, .arg)) { .memory => { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .byval => return .byval, @@ -7158,15 +7159,15 @@ const ParamTypeIterator = struct { it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)}; it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; it.types_len = 1; - it.llvm_index += 1; it.zig_index += 1; + it.llvm_index += 1; return .multiple_llvm_types; } }, .indirect => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, }, @@ -7177,10 +7178,56 @@ const ParamTypeIterator = struct { if (isScalar(zcu, ty)) { return .byval; } else { - it.byval_attr = true; + it.byval_attr = .{}; return .byref; } }, + .x86_sysv, .x86_win, .x86_mingw => { + if (isByRef(ty, zcu)) { + var items_buf: [1]codegen.FlattenedItem = undefined; + if (codegen.flattenType(&items_buf, ty, zcu, .{ + .allow_arrays = false, + })) |items| one_float: { + if (items.len != 1 or items[0].offset != 0) break :one_float; + const item_ty = items[0].type orelse break :one_float; + if (!item_ty.isRuntimeFloat()) break :one_float; + it.types_buffer[0..1].*, it.offsets_buffer[0..2].* = + switch (item_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 32 => .{ .{.float}, .{ 0, 4 } }, + 64 => .{ .{.double}, .{ 0, 8 } }, + 16, 80, 128 => break :one_float, + }; + it.types_len = 1; + it.zig_index += 1; + it.llvm_index += 1; + return .multiple_llvm_types; + } + it.zig_index += 1; + it.llvm_index += 1; + it.byval_attr = .{ .alignment = .@"4" }; + return .byref; + } + if (ty.isAbiInt(zcu)) switch (ty.intInfo(zcu).bits) { + else => unreachable, + 8, 16, 32, 64 => { + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, + 128 => { + it.types_buffer[0..2].* = .{ .i64, .i64 }; + it.offsets_buffer[0..3].* = .{ 0, 8, 16 }; + it.types_len = 2; + it.zig_index += 1; + it.llvm_index += 2; + return .multiple_llvm_types; + }, + }; + it.zig_index += 1; + it.llvm_index += 1; + return .byval; + }, .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty), .x86_64_win => return it.next_x86_64_win(ty), // TODO investigate other callconvs @@ -7277,7 +7324,7 @@ const ParamTypeIterator = struct { .x87 => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .x87up => unreachable, @@ -7285,7 +7332,7 @@ const ParamTypeIterator = struct { .memory => { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; }, .win_i128 => unreachable, // windows only @@ -7306,7 +7353,7 @@ const ParamTypeIterator = struct { if (it.llvm_index + classes_len > 6) { it.zig_index += 1; it.llvm_index += 1; - it.byval_attr = true; + it.byval_attr = .{}; return .byref; } } else if (!isByRef(ty, zcu)) { @@ -7340,7 +7387,7 @@ pub fn iterateParamTypes( .types_len = undefined, .types_buffer = undefined, .offsets_buffer = undefined, - .byval_attr = false, + .byval_attr = null, }; } @@ -7466,7 +7513,39 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A return .by_val; } else .sret, .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty), - .x86_sysv, .x86_win => if (isByRef(ret_ty, zcu)) .sret else .by_val, + .x86_sysv, .x86_win, .x86_mingw => if (isByRef(ret_ty, zcu)) { + switch (cc) { + else => unreachable, + .x86_sysv => return .sret, + .x86_win => {}, + .x86_mingw => { + var items_buf: [1]codegen.FlattenedItem = undefined; + if (codegen.flattenType(&items_buf, ret_ty, zcu, .{})) |items| one_float: { + if (items.len != 1 or items[0].offset != 0) break :one_float; + const item_ty = items[0].type orelse break :one_float; + if (!item_ty.isRuntimeFloat()) break :one_float; + return .{ .mem_cast = switch (item_ty.floatBits(zcu.getTarget())) { + else => unreachable, + 16 => .half, + 32 => .float, + 64 => .double, + 80, 128 => break :one_float, + } }; + } + }, + } + return switch (ret_ty.abiSize(zcu)) { + 0 => .void, + 1 => .{ .mem_cast = .i8 }, + 2 => .{ .mem_cast = .i16 }, + 4 => .{ .mem_cast = .i32 }, + 8 => .{ .mem_cast = .i64 }, + else => .sret, + }; + } else if (ret_ty.isAbiInt(zcu) and ret_ty.intInfo(zcu).bits > 64) + .sret + else + .by_val, .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty), .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty), // TODO investigate other callconvs diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 1b2aa830d23ee24903085a36db49ce1a42c91c72..52d0fc57a1d5238ac2fd837d10878083a94510c7 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4151,8 +4151,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .x86_64_regcall_v3_sysv => .LLVM_X86RegCall, .x86_64_regcall_v4_win => .LLVM_X86RegCall, .x86_64_vectorcall => .LLVM_vectorcall, - .x86_sysv => .normal, - .x86_win => .normal, + .x86_sysv, .x86_win, .x86_mingw => .normal, .x86_stdcall => .BORLAND_stdcall, .x86_fastcall => .BORLAND_msfastcall, .x86_thiscall => .BORLAND_thiscall, -- 2.54.0 From ba23bad8380f023455fed65e1631089f17e0535d Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 06:01:26 -0400 Subject: [PATCH 058/215] x86_64: implement c abi for array fields Closes #36195 --- src/codegen/x86_64/abi.zig | 41 +++-- test/c_abi/cfuncs.c | 240 +++++++++++++++++++++++++ test/c_abi/main.zig | 350 +++++++++++++++++++++++++++++++++++++ 3 files changed, 621 insertions(+), 10 deletions(-) diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 0bff5bd60a2f7e918dda9fd5835d653378686cff..1e01ff508af3a29367f9cfbb1ea74d412147d70a 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -358,11 +358,10 @@ fn classifySystemVStruct( while (field_it.next()) |field_index| { const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index); - byte_offset = std.mem.alignForward( - u64, - byte_offset, - field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?, - ); + byte_offset = switch (field_align) { + .none => field_ty.abiAlignment(zcu), + else => field_align, + }.forward(byte_offset); if (zcu.typeToStruct(field_ty)) |field_loaded_struct| { switch (field_loaded_struct.layout) { .auto => unreachable, @@ -381,6 +380,9 @@ fn classifySystemVStruct( }, .@"packed" => {}, } + } else if (field_ty.zigTypeTag(zcu) == .array) { + byte_offset = classifySystemVArray(result, byte_offset, field_ty, zcu, target); + continue; } const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| @@ -388,11 +390,7 @@ fn classifySystemVStruct( byte_offset += field_ty.abiSize(zcu); } const final_byte_offset = starting_byte_offset + loaded_struct.size; - std.debug.assert(final_byte_offset == std.mem.alignForward( - u64, - byte_offset, - loaded_struct.alignment.toByteUnits().?, - )); + std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset)); return final_byte_offset; } @@ -424,6 +422,9 @@ fn classifySystemVUnion( }, .@"packed" => {}, } + } else if (field_ty.zigTypeTag(zcu) == .array) { + _ = classifySystemVArray(result, starting_byte_offset, field_ty, zcu, target); + continue; } const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| @@ -432,6 +433,26 @@ fn classifySystemVUnion( return starting_byte_offset + loaded_union.size; } +fn classifySystemVArray( + result: *[8]Class, + starting_byte_offset: u64, + array_ty: Type, + zcu: *Zcu, + target: *const std.Target, +) u64 { + const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none); + var byte_offset = starting_byte_offset; + const elem_size = array_ty.childType(zcu).abiSize(zcu); + for (0..@intCast(array_ty.arrayLen(zcu))) |_| { + for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| + result_class.* = result_class.combineSystemV(field_class); + byte_offset += elem_size; + } + const final_byte_offset = starting_byte_offset + array_ty.abiSize(zcu); + assert(final_byte_offset == byte_offset); + return final_byte_offset; +} + pub const zigcc = struct { pub const stack_align: ?InternPool.Alignment = null; pub const return_in_regs = true; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index 91a33b24ad4d3ffbefc648495d1291491827677c..a1471283bfbc5ce35b9bdd4edd6e6cb6df81d831 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -15194,6 +15194,126 @@ void c_test_struct_f32_f32_f32_f32_f32(void) { zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11); } +struct Struct_array_1_f32 { + float a[1]; +}; + +struct Struct_array_1_f32 zig_ret_struct_array_1_f32(void); +void zig_struct_array_1_f32(struct Struct_array_1_f32, size_t); + +struct Struct_array_1_f32 c_ret_struct_array_1_f32(void) { + return (struct Struct_array_1_f32){ .a = { 4 } }; +} +void c_struct_array_1_f32(struct Struct_array_1_f32 s, size_t i) { + assert_or_panic(s.a[0] == 5); + assert_or_panic(i == 6); +} +void c_test_struct_array_1_f32(void) { + struct Struct_array_1_f32 s = zig_ret_struct_array_1_f32(); + assert_or_panic(s.a[0] == 1); + zig_struct_array_1_f32((struct Struct_array_1_f32){ .a = { 2 } }, 3); +} + +struct Struct_array_2_f32 { + float a[2]; +}; + +struct Struct_array_2_f32 zig_ret_struct_array_2_f32(void); +void zig_struct_array_2_f32(struct Struct_array_2_f32, size_t); + +struct Struct_array_2_f32 c_ret_struct_array_2_f32(void) { + return (struct Struct_array_2_f32){ .a = { 6, 7 } }; +} +void c_struct_array_2_f32(struct Struct_array_2_f32 s, size_t i) { + assert_or_panic(s.a[0] == 8); + assert_or_panic(s.a[1] == 9); + assert_or_panic(i == 10); +} +void c_test_struct_array_2_f32(void) { + struct Struct_array_2_f32 s = zig_ret_struct_array_2_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + zig_struct_array_2_f32((struct Struct_array_2_f32){ .a = { 3, 4 } }, 5); +} + +struct Struct_array_3_f32 { + float a[3]; +}; + +struct Struct_array_3_f32 zig_ret_struct_array_3_f32(void); +void zig_struct_array_3_f32(struct Struct_array_3_f32, size_t); + +struct Struct_array_3_f32 c_ret_struct_array_3_f32(void) { + return (struct Struct_array_3_f32){ .a = { 8, 9, 10 } }; +} +void c_struct_array_3_f32(struct Struct_array_3_f32 s, size_t i) { + assert_or_panic(s.a[0] == 11); + assert_or_panic(s.a[1] == 12); + assert_or_panic(s.a[2] == 13); + assert_or_panic(i == 14); +} +void c_test_struct_array_3_f32(void) { + struct Struct_array_3_f32 s = zig_ret_struct_array_3_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + zig_struct_array_3_f32((struct Struct_array_3_f32){ .a = { 4, 5, 6 } }, 7); +} + +struct Struct_array_4_f32 { + float a[4]; +}; + +struct Struct_array_4_f32 zig_ret_struct_array_4_f32(void); +void zig_struct_array_4_f32(struct Struct_array_4_f32, size_t); + +struct Struct_array_4_f32 c_ret_struct_array_4_f32(void) { + return (struct Struct_array_4_f32){ .a = { 10, 11, 12, 13 } }; +} +void c_struct_array_4_f32(struct Struct_array_4_f32 s, size_t i) { + assert_or_panic(s.a[0] == 14); + assert_or_panic(s.a[1] == 15); + assert_or_panic(s.a[2] == 16); + assert_or_panic(s.a[3] == 17); + assert_or_panic(i == 18); +} +void c_test_struct_array_4_f32(void) { + struct Struct_array_4_f32 s = zig_ret_struct_array_4_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + zig_struct_array_4_f32((struct Struct_array_4_f32){ .a = { 5, 6, 7, 8 } }, 9); +} + +struct Struct_array_5_f32 { + float a[5]; +}; + +struct Struct_array_5_f32 zig_ret_struct_array_5_f32(void); +void zig_struct_array_5_f32(struct Struct_array_5_f32, size_t); + +struct Struct_array_5_f32 c_ret_struct_array_5_f32(void) { + return (struct Struct_array_5_f32){ .a = { 12, 13, 14, 15, 16 } }; +} +void c_struct_array_5_f32(struct Struct_array_5_f32 s, size_t i) { + assert_or_panic(s.a[0] == 17); + assert_or_panic(s.a[1] == 18); + assert_or_panic(s.a[2] == 19); + assert_or_panic(s.a[3] == 20); + assert_or_panic(s.a[4] == 21); + assert_or_panic(i == 22); +} +void c_test_struct_array_5_f32(void) { + struct Struct_array_5_f32 s = zig_ret_struct_array_5_f32(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + assert_or_panic(s.a[4] == 5); + zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11); +} + struct Struct_f32a8 { alignas(8) float a; }; @@ -15409,6 +15529,126 @@ void c_test_struct_f64_f64_f64_f64_f64(void) { zig_struct_f64_f64_f64_f64_f64((struct Struct_f64_f64_f64_f64_f64){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11); } +struct Struct_array_1_f64 { + double a[1]; +}; + +struct Struct_array_1_f64 zig_ret_struct_array_1_f64(void); +void zig_struct_array_1_f64(struct Struct_array_1_f64, size_t); + +struct Struct_array_1_f64 c_ret_struct_array_1_f64(void) { + return (struct Struct_array_1_f64){ .a = { 4 } }; +} +void c_struct_array_1_f64(struct Struct_array_1_f64 s, size_t i) { + assert_or_panic(s.a[0] == 5); + assert_or_panic(i == 6); +} +void c_test_struct_array_1_f64(void) { + struct Struct_array_1_f64 s = zig_ret_struct_array_1_f64(); + assert_or_panic(s.a[0] == 1); + zig_struct_array_1_f64((struct Struct_array_1_f64){ .a = { 2 } }, 3); +} + +struct Struct_array_2_f64 { + double a[2]; +}; + +struct Struct_array_2_f64 zig_ret_struct_array_2_f64(void); +void zig_struct_array_2_f64(struct Struct_array_2_f64, size_t); + +struct Struct_array_2_f64 c_ret_struct_array_2_f64(void) { + return (struct Struct_array_2_f64){ .a = { 6, 7 } }; +} +void c_struct_array_2_f64(struct Struct_array_2_f64 s, size_t i) { + assert_or_panic(s.a[0] == 8); + assert_or_panic(s.a[1] == 9); + assert_or_panic(i == 10); +} +void c_test_struct_array_2_f64(void) { + struct Struct_array_2_f64 s = zig_ret_struct_array_2_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + zig_struct_array_2_f64((struct Struct_array_2_f64){ .a = { 3, 4 } }, 5); +} + +struct Struct_array_3_f64 { + double a[3]; +}; + +struct Struct_array_3_f64 zig_ret_struct_array_3_f64(void); +void zig_struct_array_3_f64(struct Struct_array_3_f64, size_t); + +struct Struct_array_3_f64 c_ret_struct_array_3_f64(void) { + return (struct Struct_array_3_f64){ .a = { 8, 9, 10 } }; +} +void c_struct_array_3_f64(struct Struct_array_3_f64 s, size_t i) { + assert_or_panic(s.a[0] == 11); + assert_or_panic(s.a[1] == 12); + assert_or_panic(s.a[2] == 13); + assert_or_panic(i == 14); +} +void c_test_struct_array_3_f64(void) { + struct Struct_array_3_f64 s = zig_ret_struct_array_3_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + zig_struct_array_3_f64((struct Struct_array_3_f64){ .a = { 4, 5, 6 } }, 7); +} + +struct Struct_array_4_f64 { + double a[4]; +}; + +struct Struct_array_4_f64 zig_ret_struct_array_4_f64(void); +void zig_struct_array_4_f64(struct Struct_array_4_f64, size_t); + +struct Struct_array_4_f64 c_ret_struct_array_4_f64(void) { + return (struct Struct_array_4_f64){ .a = { 10, 11, 12, 13 } }; +} +void c_struct_array_4_f64(struct Struct_array_4_f64 s, size_t i) { + assert_or_panic(s.a[0] == 14); + assert_or_panic(s.a[1] == 15); + assert_or_panic(s.a[2] == 16); + assert_or_panic(s.a[3] == 17); + assert_or_panic(i == 18); +} +void c_test_struct_array_4_f64(void) { + struct Struct_array_4_f64 s = zig_ret_struct_array_4_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + zig_struct_array_4_f64((struct Struct_array_4_f64){ .a = { 5, 6, 7, 8 } }, 9); +} + +struct Struct_array_5_f64 { + double a[5]; +}; + +struct Struct_array_5_f64 zig_ret_struct_array_5_f64(void); +void zig_struct_array_5_f64(struct Struct_array_5_f64, size_t); + +struct Struct_array_5_f64 c_ret_struct_array_5_f64(void) { + return (struct Struct_array_5_f64){ .a = { 12, 13, 14, 15, 16 } }; +} +void c_struct_array_5_f64(struct Struct_array_5_f64 s, size_t i) { + assert_or_panic(s.a[0] == 17); + assert_or_panic(s.a[1] == 18); + assert_or_panic(s.a[2] == 19); + assert_or_panic(s.a[3] == 20); + assert_or_panic(s.a[4] == 21); + assert_or_panic(i == 22); +} +void c_test_struct_array_5_f64(void) { + struct Struct_array_5_f64 s = zig_ret_struct_array_5_f64(); + assert_or_panic(s.a[0] == 1); + assert_or_panic(s.a[1] == 2); + assert_or_panic(s.a[2] == 3); + assert_or_panic(s.a[3] == 4); + assert_or_panic(s.a[4] == 5); + zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11); +} + struct Struct_u32_Union_u32_u32u32 { uint32_t a; union { diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index f1bbd96806d3b507ee0448f4415f811aae2d929a..16b99134cf70bc44a77179f48c68704d7a9041ec 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -16085,6 +16085,181 @@ test "struct f32, f32, f32, f32, f32" { c_test_struct_f32_f32_f32_f32_f32(); } +const Struct_array_1_f32 = extern struct { + a: [1]f32, +}; + +comptime { + skip: { + if (builtin.cpu.arch.isWasm()) break :skip; + + _ = struct { + export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 { + return .{ .a = .{1} }; + } + export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void { + expect(s.a[0] == 2) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); + } + }; + } +} + +extern fn c_ret_struct_array_1_f32() Struct_array_1_f32; +extern fn c_struct_array_1_f32(Struct_array_1_f32, usize) void; +extern fn c_test_struct_array_1_f32() void; + +test "struct [1]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; + + const s = c_ret_struct_array_1_f32(); + try expect(s.a[0] == 4); + c_struct_array_1_f32(.{ .a = .{5} }, 6); + c_test_struct_array_1_f32(); +} + +const Struct_array_2_f32 = extern struct { + a: [2]f32, +}; + +export fn zig_ret_struct_array_2_f32() Struct_array_2_f32 { + return .{ .a = .{ 1, 2 } }; +} +export fn zig_struct_array_2_f32(s: Struct_array_2_f32, i: usize) void { + expect(s.a[0] == 3) catch @panic("test failure"); + expect(s.a[1] == 4) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_2_f32() Struct_array_2_f32; +extern fn c_struct_array_2_f32(Struct_array_2_f32, usize) void; +extern fn c_test_struct_array_2_f32() void; + +test "struct [2]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + + const s = c_ret_struct_array_2_f32(); + try expect(s.a[0] == 6); + try expect(s.a[1] == 7); + c_struct_array_2_f32(.{ .a = .{ 8, 9 } }, 10); + c_test_struct_array_2_f32(); +} + +const Struct_array_3_f32 = extern struct { + a: [3]f32, +}; + +export fn zig_ret_struct_array_3_f32() Struct_array_3_f32 { + return .{ .a = .{ 1, 2, 3 } }; +} +export fn zig_struct_array_3_f32(s: Struct_array_3_f32, i: usize) void { + expect(s.a[0] == 4) catch @panic("test failure"); + expect(s.a[1] == 5) catch @panic("test failure"); + expect(s.a[2] == 6) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_3_f32() Struct_array_3_f32; +extern fn c_struct_array_3_f32(Struct_array_3_f32, usize) void; +extern fn c_test_struct_array_3_f32() void; + +test "struct [3]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_3_f32(); + try expect(s.a[0] == 8); + try expect(s.a[1] == 9); + try expect(s.a[2] == 10); + c_struct_array_3_f32(.{ .a = .{ 11, 12, 13 } }, 14); + c_test_struct_array_3_f32(); +} + +const Struct_array_4_f32 = extern struct { + a: [4]f32, +}; + +export fn zig_ret_struct_array_4_f32() Struct_array_4_f32 { + return .{ .a = .{ 1, 2, 3, 4 } }; +} +export fn zig_struct_array_4_f32(s: Struct_array_4_f32, i: usize) void { + expect(s.a[0] == 5) catch @panic("test failure"); + expect(s.a[1] == 6) catch @panic("test failure"); + expect(s.a[2] == 7) catch @panic("test failure"); + expect(s.a[3] == 8) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_4_f32() Struct_array_4_f32; +extern fn c_struct_array_4_f32(Struct_array_4_f32, usize) void; +extern fn c_test_struct_array_4_f32() void; + +test "struct [4]f32" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_4_f32(); + try expect(s.a[0] == 10); + try expect(s.a[1] == 11); + try expect(s.a[2] == 12); + try expect(s.a[3] == 13); + c_struct_array_4_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18); + c_test_struct_array_4_f32(); +} + +const Struct_array_5_f32 = extern struct { + a: [5]f32, +}; + +export fn zig_ret_struct_array_5_f32() Struct_array_5_f32 { + return .{ .a = .{ 1, 2, 3, 4, 5 } }; +} +export fn zig_struct_array_5_f32(s: Struct_array_5_f32, i: usize) void { + expect(s.a[0] == 6) catch @panic("test failure"); + expect(s.a[1] == 7) catch @panic("test failure"); + expect(s.a[2] == 8) catch @panic("test failure"); + expect(s.a[3] == 9) catch @panic("test failure"); + expect(s.a[4] == 10) catch @panic("test failure"); + expect(i == 11) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_5_f32() Struct_array_5_f32; +extern fn c_struct_array_5_f32(Struct_array_5_f32, usize) void; +extern fn c_test_struct_array_5_f32() void; + +test "struct [5]f32" { + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_5_f32(); + try expect(s.a[0] == 12); + try expect(s.a[1] == 13); + try expect(s.a[2] == 14); + try expect(s.a[3] == 15); + try expect(s.a[4] == 16); + c_struct_array_5_f32(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22); + c_test_struct_array_5_f32(); +} + const Struct_f32a8 = extern struct { a: f32 align(8), }; @@ -16382,6 +16557,181 @@ test "struct f64, f64, f64, f64, f64" { c_test_struct_f64_f64_f64_f64_f64(); } +const Struct_array_1_f64 = extern struct { + a: [1]f64, +}; + +comptime { + skip: { + if (builtin.cpu.arch.isWasm()) break :skip; + + _ = struct { + export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 { + return .{ .a = .{1} }; + } + export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void { + expect(s.a[0] == 2) catch @panic("test failure"); + expect(i == 3) catch @panic("test failure"); + } + }; + } +} + +extern fn c_ret_struct_array_1_f64() Struct_array_1_f64; +extern fn c_struct_array_1_f64(Struct_array_1_f64, usize) void; +extern fn c_test_struct_array_1_f64() void; + +test "struct [1]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + if (builtin.cpu.arch == .s390x) return error.SkipZigTest; + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; + + const s = c_ret_struct_array_1_f64(); + try expect(s.a[0] == 4); + c_struct_array_1_f64(.{ .a = .{5} }, 6); + c_test_struct_array_1_f64(); +} + +const Struct_array_2_f64 = extern struct { + a: [2]f64, +}; + +export fn zig_ret_struct_array_2_f64() Struct_array_2_f64 { + return .{ .a = .{ 1, 2 } }; +} +export fn zig_struct_array_2_f64(s: Struct_array_2_f64, i: usize) void { + expect(s.a[0] == 3) catch @panic("test failure"); + expect(s.a[1] == 4) catch @panic("test failure"); + expect(i == 5) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_2_f64() Struct_array_2_f64; +extern fn c_struct_array_2_f64(Struct_array_2_f64, usize) void; +extern fn c_test_struct_array_2_f64() void; + +test "struct [2]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; + + const s = c_ret_struct_array_2_f64(); + try expect(s.a[0] == 6); + try expect(s.a[1] == 7); + c_struct_array_2_f64(.{ .a = .{ 8, 9 } }, 10); + c_test_struct_array_2_f64(); +} + +const Struct_array_3_f64 = extern struct { + a: [3]f64, +}; + +export fn zig_ret_struct_array_3_f64() Struct_array_3_f64 { + return .{ .a = .{ 1, 2, 3 } }; +} +export fn zig_struct_array_3_f64(s: Struct_array_3_f64, i: usize) void { + expect(s.a[0] == 4) catch @panic("test failure"); + expect(s.a[1] == 5) catch @panic("test failure"); + expect(s.a[2] == 6) catch @panic("test failure"); + expect(i == 7) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_3_f64() Struct_array_3_f64; +extern fn c_struct_array_3_f64(Struct_array_3_f64, usize) void; +extern fn c_test_struct_array_3_f64() void; + +test "struct [3]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_3_f64(); + try expect(s.a[0] == 8); + try expect(s.a[1] == 9); + try expect(s.a[2] == 10); + c_struct_array_3_f64(.{ .a = .{ 11, 12, 13 } }, 14); + c_test_struct_array_3_f64(); +} + +const Struct_array_4_f64 = extern struct { + a: [4]f64, +}; + +export fn zig_ret_struct_array_4_f64() Struct_array_4_f64 { + return .{ .a = .{ 1, 2, 3, 4 } }; +} +export fn zig_struct_array_4_f64(s: Struct_array_4_f64, i: usize) void { + expect(s.a[0] == 5) catch @panic("test failure"); + expect(s.a[1] == 6) catch @panic("test failure"); + expect(s.a[2] == 7) catch @panic("test failure"); + expect(s.a[3] == 8) catch @panic("test failure"); + expect(i == 9) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_4_f64() Struct_array_4_f64; +extern fn c_struct_array_4_f64(Struct_array_4_f64, usize) void; +extern fn c_test_struct_array_4_f64() void; + +test "struct [4]f64" { + if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; + if (builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_4_f64(); + try expect(s.a[0] == 10); + try expect(s.a[1] == 11); + try expect(s.a[2] == 12); + try expect(s.a[3] == 13); + c_struct_array_4_f64(.{ .a = .{ 14, 15, 16, 17 } }, 18); + c_test_struct_array_4_f64(); +} + +const Struct_array_5_f64 = extern struct { + a: [5]f64, +}; + +export fn zig_ret_struct_array_5_f64() Struct_array_5_f64 { + return .{ .a = .{ 1, 2, 3, 4, 5 } }; +} +export fn zig_struct_array_5_f64(s: Struct_array_5_f64, i: usize) void { + expect(s.a[0] == 6) catch @panic("test failure"); + expect(s.a[1] == 7) catch @panic("test failure"); + expect(s.a[2] == 8) catch @panic("test failure"); + expect(s.a[3] == 9) catch @panic("test failure"); + expect(s.a[4] == 10) catch @panic("test failure"); + expect(i == 11) catch @panic("test failure"); +} + +extern fn c_ret_struct_array_5_f64() Struct_array_5_f64; +extern fn c_struct_array_5_f64(Struct_array_5_f64, usize) void; +extern fn c_test_struct_array_5_f64() void; + +test "struct [5]f64" { + if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; + if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + + const s = c_ret_struct_array_5_f64(); + try expect(s.a[0] == 12); + try expect(s.a[1] == 13); + try expect(s.a[2] == 14); + try expect(s.a[3] == 15); + try expect(s.a[4] == 16); + c_struct_array_5_f64(.{ .a = .{ 17, 18, 19, 20, 21 } }, 22); + c_test_struct_array_5_f64(); +} + const Struct_u32_Union_u32_u32u32 = extern struct { a: u32, b: extern union { -- 2.54.0 From 6c003e84338bc1f8ceaf7ca869cb343b31be9fc7 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 20:26:56 -0400 Subject: [PATCH 059/215] x86_64: update for compiler_rt abi changes --- src/codegen/x86_64/CodeGen.zig | 128 --------------------------------- 1 file changed, 128 deletions(-) diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 662fc600b1e863b89bdfc0f8719545786ac64dac..4958d17e304cb7cccc3e4b383bd46e1d09141c0a 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._, .call, .tmp1d, ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse, null, null, null }, .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any }, .dst_constraints = .{ .{ .float = .xword }, .any }, @@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .each = .{ .once = &.{ .{ ._, ._, .call, .tmp0d, ._, ._, ._ }, } }, - }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse, null, null, null }, - .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any }, - .dst_constraints = .{ .{ .float = .xword }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } }, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .lea, .tmp0p, .mem(.src0), ._, ._ }, - .{ ._, ._, .call, .tmp1d, ._, ._, ._ }, - } }, }, .{ .required_features = .{ .@"64bit", .sse, null, null }, .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any }, @@ -126791,7 +126762,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .avx, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126824,39 +126794,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .win64, - .required_features = .{ .avx, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, .v_dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, - }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse2, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126889,39 +126826,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse2, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, ._dqa, .mov, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, - }, .{ - .required_cc_abi = .sysv64, .required_features = .{ .sse, null, null, null }, .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, @@ -126953,38 +126857,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, } }, - }, .{ - .required_cc_abi = .win64, - .required_features = .{ .sse, null, null, null }, - .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, - .dst_constraints = .{ .{ .multiple_scalar_float = .{ .of = .xword, .is = .xword } }, .any }, - .patterns = &.{ - .{ .src = .{ .to_mem, .none, .none } }, - }, - .call_frame = .{ .alignment = .@"16" }, - .extra_temps = .{ - .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, - .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .{ .type = .usize, .kind = .{ .extern_func = "__floatuntitf" } }, - .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - .unused, - }, - .dst_temps = .{ .mem, .unused }, - .clobbers = .{ .eflags = true, .caller_preserved = .ccc }, - .each = .{ .once = &.{ - .{ ._, ._, .mov, .tmp0d, .sia(-16, .src0, .add_unaligned_size), ._, ._ }, - .{ .@"0:", ._, .lea, .tmp1p, .memi(.src0, .tmp0), ._, ._ }, - .{ ._, ._, .call, .tmp2d, ._, ._, ._ }, - .{ ._, ._ps, .mova, .memi(.dst0x, .tmp0), .tmp3x, ._, ._ }, - .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, - .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, - } }, }, .{ .required_features = .{ .@"64bit", .avx, null, null }, .src_constraints = .{ .{ .scalar_remainder_signed_int = .{ .of = .dword, .is = .dword } }, .any, .any }, -- 2.54.0 From e03056d45a864c8176cdd897d771457005ead592 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 17 Jul 2026 15:44:14 -0400 Subject: [PATCH 060/215] cbe: various calling convention fixes - Annotate function pointers with calling convention. - Support `incoming_stack_alignment`. - Fix noreturn attribute position. --- lib/zig.h | 19 +--- src/Zcu.zig | 30 +---- src/codegen/c.zig | 142 +++++++---------------- src/codegen/c/type.zig | 177 ++++++++++++++++++++++++++++- src/codegen/c/type/render_defs.zig | 16 +-- src/codegen/llvm.zig | 4 +- 6 files changed, 239 insertions(+), 149 deletions(-) diff --git a/lib/zig.h b/lib/zig.h index 139263d11132833d2c64539c2b39cf44b3bd0b89..30e6f3f96a97f47b6648db1d1587bc75c88b6c3f 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -199,10 +199,8 @@ #endif #if defined(zig_msvc) -#define zig_const_arr #define zig_callconv(c) __##c #else -#define zig_const_arr static const #define zig_callconv(c) __attribute__((c)) #endif @@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80; #define zig_init_special_f80(sign, name, arg, repr) repr #endif -#if defined(zig_gcc) && defined(zig_x86) -#define zig_f128_has_miscompilations 1 -#else -#define zig_f128_has_miscompilations 0 -#endif #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) @@ -5859,22 +5852,22 @@ typedef struct { uint64_t hi, lo; } zig_f128; #define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } #define zig_lo_repr_f128(arg) (arg).lo #define zig_hi_repr_f128(arg) (arg).hi -#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#elif FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 +#elif DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 +#elif LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 +#elif FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 +#elif FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) +#elif defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128 diff --git a/src/Zcu.zig b/src/Zcu.zig index 2af36db254d2edbcfe3ae8a05de265b882d46b01..875ffd44b29c92738f12e3cf32f300301edf2d7d 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4617,44 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .m68k_rtd, .m68k_interrupt, .msp430_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .arm_aapcs_vfp, - => |opts| opts.incoming_stack_alignment == null, - .arc_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .arm_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .microblaze_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .mips_interrupt, .mips64_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .riscv32_interrupt, .riscv64_interrupt, - => |opts| opts.incoming_stack_alignment == null, - .sh_interrupt, - => |opts| opts.incoming_stack_alignment == null, + .avr_interrupt, + .avr_signal, + .ez80_tiflags, + .naked, + => true, // incoming stack alignment supported .x86_sysv, .x86_win, .x86_mingw, .x86_stdcall, - => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, - - .avr_interrupt, - .avr_signal, - => true, - - .ez80_tiflags => true, - - .naked => true, + => |opts| opts.register_params == 0, // incoming stack alignment supported else => false, }; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 1633321426dfc3044177eebe0cd44e6fda3c6aa9..5ab86a9a5fad9e1a4391053bd5e1af970de1feeb 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1750,8 +1750,6 @@ pub const DeclGen = struct { try w.writeAll("zig_no_builtin "); } - if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); - // While incomplete types are usually an acceptable substitute for "void", this is not true // in function return types, where "void" is the only incomplete type permitted. const actual_return_type: Type = .fromInterned(fn_info.return_type); @@ -1763,8 +1761,9 @@ pub const DeclGen = struct { const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); - if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { - try w.print("zig_callconv({s}) ", .{call_conv}); + switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), } switch (name) { .nav => |nav| try renderNavName(w, nav, ip), @@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn( const fn_val = zcu.navValue(fn_nav); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.print("static zig_{t} ", .{kind}); try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { .never_tail => .{ .nav_never_tail = fn_nav }, @@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E const gpa = f.dg.gpa; const nav_index = f.dg.owner_nav.unwrap().?; const nav_val = zcu.navValue(nav_index); + const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?; const nav = ip.getNav(nav_index); + if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn "); try fwd_decl_writer.writeAll("static "); try f.dg.renderFunctionSignature( fwd_decl_writer, @@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E const main_body = f.air.getMainBody(); f.indent(); + if (switch (fn_info.cc) { + inline else => |pl| switch (@TypeOf(pl)) { + void, + std.lang.CallingConvention.SpirvKernelOptions, + std.lang.CallingConvention.SpirvFragmentOptions, + std.lang.CallingConvention.SpirvMeshOptions, + => null, + std.lang.CallingConvention.ArcInterruptOptions, + std.lang.CallingConvention.ArmInterruptOptions, + std.lang.CallingConvention.RiscvInterruptOptions, + std.lang.CallingConvention.ShInterruptOptions, + std.lang.CallingConvention.MicroblazeInterruptOptions, + std.lang.CallingConvention.MipsInterruptOptions, + std.lang.CallingConvention.CommonOptions, + std.lang.CallingConvention.X86RegparmOptions, + => pl.incoming_stack_alignment, + else => @compileError(@tagName(pl)), + }, + }) |incoming_stack_alignment| realign_stack: { + const normal_stack_align = zcu.getTarget().stackAlignment(); + if (incoming_stack_alignment >= normal_stack_align) break :realign_stack; + try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{ + normal_stack_align << 1, + }); + try f.code.writer.writeAll( + \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack)); + ); + try f.newline(); + } try genBodyResolveState(f, undefined, &.{}, main_body, true); try f.outdent(); try f.code.writer.writeByte('}'); @@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { .@"fn" => { + const fn_val: Value = .fromInterned(nav.resolved.?.value); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.writeAll("zig_extern "); try dg.renderFunctionSignature( w, - .fromInterned(nav.resolved.?.value), + fn_val, nav.resolved.?.@"align", .forward_decl, .{ .@"export" = .{ @@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic const exported_val = exported.getValue(zcu); if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { const @"export" = export_index.ptr(zcu); + const fn_val = exported.getValue(zcu); + if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); try w.writeAll("zig_extern "); if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); try dg.renderFunctionSignature( w, - exported.getValue(zcu), + fn_val, exported.getAlign(zcu), .forward_decl, .{ .@"export" = .{ @@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void { return w.writeAll(toMemoryOrder(order)); } -fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 { - if (zcu.getTarget().cCallingConvention()) |ccc| { - if (cc.eql(ccc)) { - return null; - } - } - return switch (cc) { - .auto, .naked => null, - - .x86_16_cdecl => "cdecl", - .x86_16_regparmcall => "regparmcall", - .x86_64_sysv, .x86_sysv => "sysv_abi", - .x86_64_win, .x86_win, .x86_mingw => "ms_abi", - .x86_16_stdcall, .x86_stdcall => "stdcall", - .x86_fastcall => "fastcall", - .x86_thiscall => "thiscall", - - .x86_vectorcall, - .x86_64_vectorcall, - => "vectorcall", - - .x86_64_regcall_v3_sysv, - .x86_64_regcall_v4_win, - .x86_regcall_v3, - .x86_regcall_v4_win, - => "regcall", - - .aarch64_vfabi => "aarch64_vector_pcs", - .aarch64_vfabi_sve => "aarch64_sve_pcs", - - .arm_aapcs => "pcs(\"aapcs\")", - .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")", - - .arc_interrupt => |opts| switch (opts.type) { - inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")", - }, - - .arm_interrupt => |opts| switch (opts.type) { - .generic => "interrupt", - .irq => "interrupt(\"IRQ\")", - .fiq => "interrupt(\"FIQ\")", - .swi => "interrupt(\"SWI\")", - .abort => "interrupt(\"ABORT\")", - .undef => "interrupt(\"UNDEF\")", - }, - - .avr_signal => "signal", - - .microblaze_interrupt => |opts| switch (opts.type) { - .user => "save_volatiles", - .regular => "interrupt_handler", - .fast => "fast_interrupt", - .breakpoint => "break_handler", - }, - - .mips_interrupt, - .mips64_interrupt, - => |opts| switch (opts.mode) { - inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", - }, - - .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc", - - .riscv32_interrupt, - .riscv64_interrupt, - => |opts| switch (opts.mode) { - inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", - }, - - .sh_renesas => "renesas", - .sh_interrupt => |opts| switch (opts.save) { - .fpscr => "trapa_handler", // Implies `interrupt_handler`. - .high => "interrupt_handler, nosave_low_regs", - .full => "interrupt_handler", - .bank => "interrupt_handler, resbank", - }, - - .m68k_rtd => "m68k_rtd", - - .avr_interrupt, - .csky_interrupt, - .m68k_interrupt, - .msp430_interrupt, - .x86_16_interrupt, - .x86_interrupt, - .x86_64_interrupt, - => "interrupt", - - .ez80_tiflags, - => "__tiflags__", - - else => unreachable, // `Zcu.callconvSupported` - }; -} - fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 { return switch (order) { .Xchg => "xchg", diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 41ce79a2f5ef333ad5d319f0fbbdd544d9347409..347dc7e16e27dce1c3dd41b006f860f5772fce6c 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -44,8 +44,175 @@ pub const CType = union(enum) { param_tys: []const CType, ret_ty: *const CType, varargs: bool, + cc: CallingConvention, }, + pub const CallingConvention = enum { + c, + + cdecl, + regparmcall, + sysv_abi, + ms_abi, + stdcall, + fastcall, + thiscall, + + vectorcall, + + regcall, + + aarch64_vector_pcs, + aarch64_sve_pcs, + + @"pcs(\"aapcs\")", + @"pcs(\"aapcs-vfp\")", + + @"interrupt(\"ilink1\")", + @"interrupt(\"ilink2\")", + @"interrupt(\"ilink\")", + @"interrupt(\"firq\")", + + interrupt, + @"interrupt(\"IRQ\")", + @"interrupt(\"FIQ\")", + @"interrupt(\"SWI\")", + @"interrupt(\"ABORT\")", + @"interrupt(\"UNDEF\")", + + signal, + + save_volatiles, + interrupt_handler, + fast_interrupt, + break_handler, + + @"interrupt(\"eic\")", + @"interrupt(\"sw0\")", + @"interrupt(\"sw1\")", + @"interrupt(\"hw0\")", + @"interrupt(\"hw1\")", + @"interrupt(\"hw2\")", + @"interrupt(\"hw3\")", + @"interrupt(\"hw4\")", + @"interrupt(\"hw5\")", + + riscv_vector_cc, + @"interrupt(\"supervisor\")", + @"interrupt(\"machine\")", + + renesas, + /// Implies `interrupt_handler`. + trapa_handler, + @"interrupt_handler, nosave_low_regs", + @"interrupt_handler, resbank", + + m68k_rtd, + + tiflags, + + pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention { + if (target.cCallingConvention()) |ccc| { + if (cc.eql(ccc)) { + return .c; + } + } + return switch (cc) { + .auto, .naked => .c, + + .x86_16_cdecl => .cdecl, + .x86_16_regparmcall => .regparmcall, + .x86_64_sysv, .x86_sysv => .sysv_abi, + .x86_64_win, .x86_win, .x86_mingw => .ms_abi, + .x86_16_stdcall, .x86_stdcall => .stdcall, + .x86_fastcall => .fastcall, + .x86_thiscall => .thiscall, + + .x86_vectorcall, + .x86_64_vectorcall, + => .vectorcall, + + .x86_64_regcall_v3_sysv, + .x86_64_regcall_v4_win, + .x86_regcall_v3, + .x86_regcall_v4_win, + => .regcall, + + .aarch64_vfabi => .aarch64_vector_pcs, + .aarch64_vfabi_sve => .aarch64_sve_pcs, + + .arm_aapcs => .@"pcs(\"aapcs\")", + .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")", + + .arc_interrupt => |opts| switch (opts.type) { + .ilink1 => .@"interrupt(\"ilink1\")", + .ilink2 => .@"interrupt(\"ilink2\")", + .ilink => .@"interrupt(\"ilink\")", + .firq => .@"interrupt(\"firq\")", + }, + + .arm_interrupt => |opts| switch (opts.type) { + .generic => .interrupt, + .irq => .@"interrupt(\"IRQ\")", + .fiq => .@"interrupt(\"FIQ\")", + .swi => .@"interrupt(\"SWI\")", + .abort => .@"interrupt(\"ABORT\")", + .undef => .@"interrupt(\"UNDEF\")", + }, + + .avr_signal => .signal, + + .microblaze_interrupt => |opts| switch (opts.type) { + .user => .save_volatiles, + .regular => .interrupt_handler, + .fast => .fast_interrupt, + .breakpoint => .break_handler, + }, + + .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) { + .eic => .@"interrupt(\"eic\")", + .sw0 => .@"interrupt(\"sw0\")", + .sw1 => .@"interrupt(\"sw1\")", + .hw0 => .@"interrupt(\"hw0\")", + .hw1 => .@"interrupt(\"hw1\")", + .hw2 => .@"interrupt(\"hw2\")", + .hw3 => .@"interrupt(\"hw3\")", + .hw4 => .@"interrupt(\"hw4\")", + .hw5 => .@"interrupt(\"hw5\")", + }, + + .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc, + .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) { + .supervisor => .@"interrupt(\"supervisor\")", + .machine => .@"interrupt(\"machine\")", + }, + + .sh_renesas => .renesas, + .sh_interrupt => |opts| switch (opts.save) { + .fpscr => .trapa_handler, + .high => .@"interrupt_handler, nosave_low_regs", + .full => .interrupt_handler, + .bank => .@"interrupt_handler, resbank", + }, + + .m68k_rtd => .m68k_rtd, + + .avr_interrupt, + .csky_interrupt, + .m68k_interrupt, + .msp430_interrupt, + .x86_16_interrupt, + .x86_interrupt, + .x86_64_interrupt, + => .interrupt, + + .ez80_tiflags => .tiflags, + + else => unreachable, // `Zcu.callconvSupported` + }; + } + }; + /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears /// after the identifier in a declarator with this type. In this case, if this node is wrapped /// in a pointer type, we will need to add parentheses due to operator precedence. @@ -376,6 +543,7 @@ pub const CType = union(enum) { .ret_ty = ret_cty_buf, .param_tys = param_cty_buf, .varargs = func_type.is_var_args, + .cc = .fromLang(func_type.cc, zcu.getTarget()), } }; } try deps.addType(gpa, cur_ty, allow_incomplete); @@ -763,6 +931,13 @@ pub const CType = union(enum) { try w.writeByte('('); }, } + switch (ptr.elem_ty.*) { + else => {}, + .function => |function| switch (function.cc) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), + }, + } try w.writeByte('*'); }, @@ -812,7 +987,7 @@ pub const CType = union(enum) { => {}, .pointer => |ptr| { - // Match opening paren "(" write `writeTypePrefix`. + // Match opening paren "(" in `writeTypePrefix`. switch (ptr.elem_ty.kind()) { .specifier, .pointer => {}, .postfix_op => try w.writeByte(')'), diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index d591c09bf16d71b77c4d7b2dc3c4659665dd94a1..2ba76d64eda0073dc0cdb032d117fedf16fba0ae 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -203,10 +203,12 @@ pub fn defineComplete( const name_cty: CType = .{ .@"fn" = ty }; const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); - try w.print("typedef {f}{f}(", .{ - ret_cty.fmtDeclaratorPrefix(zcu), - name_cty.fmtTypeName(zcu), - }); + try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); + switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) { + .c => {}, + else => |cc| try w.print("zig_callconv({t}) ", .{cc}), + } + try w.print("{f}(", .{name_cty.fmtTypeName(zcu)}); var any_params = false; for (func_type.param_types.get(ip)) |param_ty_ip| { const param_ty: Type = .fromInterned(param_ty_ip); @@ -222,9 +224,7 @@ pub fn defineComplete( } else if (!any_params) { try w.writeAll("void"); } - try w.print("){f};", .{ - ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), - }); + try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); break :check_cty null; }, .@"enum" => { @@ -254,7 +254,7 @@ pub fn defineComplete( try w.print( \\{f} {{ \\ {f}ptr{f}; - \\ size_t len; + \\ uintptr_t len; \\}}; , .{ name_cty.fmtTypeName(zcu), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index de5f084008896d56c36ff371078b6581a306a45f..31e67026821a109d79a6e677014fa0bcf8712615 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2550,7 +2550,7 @@ pub const Object = struct { llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); if (cc_info.align_stack) { - try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); + try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder); } if (cc_info.naked) { @@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target) std.lang.CallingConvention.SpirvFragmentOptions, std.lang.CallingConvention.SpirvMeshOptions, => .{ null, 0, 0 }, - else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)), + else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"), }, }; return .{ -- 2.54.0 From 556e9a455c1372d39bf7e73513d879aa199acc07 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 16 Jul 2026 12:48:14 -0400 Subject: [PATCH 061/215] llvm: work around bizarre upstream llvm behavior --- src/codegen/llvm/FuncGen.zig | 50 ++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 1dfdfba987f0e962049294699bba1bcce3aac4bf..2bdd059f1fe217c8675e5faa9acead19208c2cf3 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -2040,7 +2040,7 @@ fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target)) return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), ""); const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse { @@ -2093,7 +2093,7 @@ fn airIntFromFloat( const dest_llvm_ty = try o.lowerType(dest_ty, .as_value); const dest_scalar_info = dest_scalar_ty.intInfo(zcu); - if (intrinsicsAllowed(operand_scalar_ty, target)) { + if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) { // TODO set fast math flag return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, ""); } @@ -3888,7 +3888,7 @@ fn buildFloatCmp( const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - if (intrinsicsAllowed(scalar_ty, target)) { + if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { .eq => .oeq, .neq => .une, @@ -3968,10 +3968,14 @@ fn buildFloatOp( const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { + switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics - .neg => return fg.wip.un(.fneg, params[0], ""), - .add, .sub, .mul, .div, .fmod => return fg.wip.bin(switch (fast) { + .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""), + .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) { + else => unreachable, + .add, .sub, .mul, .div => .compiler_rt, + .fmod => .libc, + }, scalar_ty, target)) return fg.wip.bin(switch (fast) { .normal => switch (op) { .add => .fadd, .sub => .fsub, @@ -3989,6 +3993,7 @@ fn buildFloatOp( else => unreachable, }, }, params[0], params[1], ""), + .fma, .fmax, .fmin, .ceil, @@ -4003,9 +4008,10 @@ fn buildFloatOp( .round, .sin, .sqrt, + .tan, .trunc, - .fma, - => return fg.wip.callIntrinsic(fast, .none, switch (op) { + => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) { + .fma => .fma, .fmax => .maxnum, .fmin => .minnum, .ceil => .ceil, @@ -4020,12 +4026,11 @@ fn buildFloatOp( .round => .round, .sin => .sin, .sqrt => .sqrt, + .tan => .tan, .trunc => .trunc, - .fma => .fma, else => unreachable, }, &.{try o.lowerType(ty, .as_value)}, ¶ms, ""), - .tan => unreachable, - }; + } const float_bits = scalar_ty.floatBits(target); const fn_name = switch (op) { @@ -4589,7 +4594,8 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and + intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); const dest_bits = dest_scalar_ty.floatBits(target); const src_bits = operand_scalar_ty.floatBits(target); @@ -4610,7 +4616,8 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const dest_scalar_ty = dest_ty.scalarType(zcu); const target = zcu.getTarget(); - if (intrinsicsAllowed(dest_scalar_ty, target) and intrinsicsAllowed(operand_scalar_ty, target)) + if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and + intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); const dest_bits = dest_scalar_ty.floatBits(target); const src_bits = operand_scalar_ty.floatBits(target); @@ -6161,7 +6168,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All .@"vector.reduce.umax", else => unreachable, }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), - .float => if (intrinsicsAllowed(scalar_ty, target)) + .float => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Min => .@"vector.reduce.fmin", .Max => .@"vector.reduce.fmax", @@ -6175,7 +6182,7 @@ fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) All .Mul => .@"vector.reduce.mul", else => unreachable, }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), - .float => if (intrinsicsAllowed(scalar_ty, target)) + .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { .Add => .@"vector.reduce.fadd", .Mul => .@"vector.reduce.fmul", @@ -7936,9 +7943,18 @@ fn appendConstraints( /// LLVM does not support all relevant intrinsics for all targets, so we /// may need to manually generate a compiler-rt call using a soft type. -fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool { +fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool { if (!scalar_ty.isRuntimeFloat()) return true; - return switch (std.zig.target.compilerRtFloatAbi(target, scalar_ty.floatBits(target))) { + const bits = scalar_ty.floatBits(target); + // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides + // that it is a much better idea to just emit a call to the entirely wrong function as + // a fallback. We wouldn't want any linker errors when trying to perform an operation + // that isn't actually implemented anywhere, now would we! + if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) { + .compiler_rt => true, + .libc => false, + }; + return switch (std.zig.target.compilerRtFloatAbi(target, bits)) { .hard => true, .soft => false, }; -- 2.54.0 From 3b8913a321dbd0ff7de7ac5ac9d4dd82a4235a2e Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 23 Jul 2026 09:49:03 -0400 Subject: [PATCH 062/215] llvm: enable passing tests Closes #10875 Closes #12396 Closes #20680 Closes #25734 Closes #30854 Closes #35519 --- lib/std/http/test.zig | 21 +-------------------- lib/std/math.zig | 2 +- lib/std/math/acos.zig | 4 ---- lib/std/math/asin.zig | 4 ---- lib/std/math/atan.zig | 4 ---- lib/std/math/hypot.zig | 9 --------- lib/std/math/isnan.zig | 8 +------- lib/std/math/modf.zig | 4 ---- lib/std/os/linux/IoUring/test.zig | 7 ------- test/behavior/align.zig | 1 - test/behavior/basic.zig | 1 - test/behavior/cast.zig | 6 ------ test/behavior/field_parent_ptr.zig | 1 - test/behavior/floatop.zig | 13 +------------ test/behavior/threadlocal.zig | 5 ----- test/behavior/union.zig | 6 ++++-- test/behavior/vector.zig | 7 ------- test/behavior/widening.zig | 1 - 18 files changed, 8 insertions(+), 96 deletions(-) diff --git a/lib/std/http/test.zig b/lib/std/http/test.zig index 39f2063f65d7c1b175ce0750e9512abaee3f2c20..e7a37daa68de6751d5762b7639e25bd1401a37c0 100644 --- a/lib/std/http/test.zig +++ b/lib/std/http/test.zig @@ -1,5 +1,4 @@ const builtin = @import("builtin"); -const native_endian = builtin.cpu.arch.endian(); const std = @import("std"); const http = std.http; @@ -34,7 +33,6 @@ test "content length reader state update" { } test "trailers" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -121,7 +119,6 @@ test "trailers" { } test "HTTP server handles a chunked transfer coding request" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" { } test "echo content server" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -281,12 +277,11 @@ test "echo content server" { } test "Server.Request.respondStreaming non-chunked, unknown content-length" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; - if (builtin.os.tag == .windows) { + if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/21457 return error.SkipZigTest; } @@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { } test "receiving arbitrary http headers from the client" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" { } test "general client/server API coverage" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; - if (builtin.os.tag == .windows) { - // This test was never passing on Windows. - return error.SkipZigTest; - } - const test_server = try createTestServer(io, struct { fn run(test_server: *TestServer) anyerror!void { const net_server = &test_server.net_server; @@ -922,7 +910,6 @@ test "general client/server API coverage" { } test "Server streams both reading and writing" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1162,10 +1149,6 @@ const TestServer = struct { fn createTestServer(io: Io, S: type) !*TestServer { if (builtin.single_threaded) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and native_endian == .big) { - // https://github.com/ziglang/zig/issues/13782 - return error.SkipZigTest; - } const address = try net.IpAddress.parse("127.0.0.1", 0); @@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer { } test "redirect to different connection" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; @@ -1280,7 +1262,6 @@ test "redirect to different connection" { } test "boot failed connections from the pool" { - if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 const io = std.testing.io; diff --git a/lib/std/math.zig b/lib/std/math.zig index ae644d6fceff795c5cb1864acada365867a19521..27d5e0d584dca43e838d31eabec11ca2134045d9 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -461,7 +461,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) { } } test wrap { - if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) { + if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) { // https://codeberg.org/ziglang/zig/issues/35520 return error.SkipZigTest; } diff --git a/lib/std/math/acos.zig b/lib/std/math/acos.zig index 285190227c75b5780d3b2678656272b2e01d068a..d79c36182e0aa6ebd784c45f56c0232905a9c1a2 100644 --- a/lib/std/math/acos.zig +++ b/lib/std/math/acos.zig @@ -337,8 +337,6 @@ fn acosBinary128(x: f128) f128 { } test "acosBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0)); try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1)); try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0)); @@ -350,8 +348,6 @@ test "acosBinary16.special" { } test "acosBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0)); try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0)); try testing.expectApproxEqAbs(0x1.b7cp0, acosBinary16(-0x1.2c4p-3), math.floatEpsAt(f16, 0x1.b7cp0)); diff --git a/lib/std/math/asin.zig b/lib/std/math/asin.zig index 68efd182aaf93db9ba5824cd76be55854c5c5f40..dfd3f063954c68d25230993b0875873273eb9ff8 100644 --- a/lib/std/math/asin.zig +++ b/lib/std/math/asin.zig @@ -326,8 +326,6 @@ fn asinBinary128(x: f128) f128 { } test "asinBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0)); try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0)); try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0)); @@ -340,8 +338,6 @@ test "asinBinary16.special" { } test "asinBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6)); try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0)); try testing.expectApproxEqAbs(-0x1.eep-1, asinBinary16(-0x1.a4cp-1), math.floatEpsAt(f16, -0x1.eep-1)); diff --git a/lib/std/math/atan.zig b/lib/std/math/atan.zig index 2d55b8bc1343d95f6671a96636d55b2b4a269c8e..75dab1b0c19732b229000d62634e7944491db254 100644 --- a/lib/std/math/atan.zig +++ b/lib/std/math/atan.zig @@ -481,8 +481,6 @@ fn atanBinary128(x: f128) f128 { } test "atanBinary16.special" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0)); try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0)); try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1)); @@ -493,8 +491,6 @@ test "atanBinary16.special" { } test "atanBinary16" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2)); try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0)); try testing.expectApproxEqAbs(-0x1.11cp0, atanBinary16(-0x1.d2cp0), math.floatEpsAt(f16, -0x1.11cp0)); diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig index ef3fc97af3d3ea21b7cb525c616d248ffc20da7d..99da74c335c342a277778f79bafe53e7fb2d7766 100644 --- a/lib/std/math/hypot.zig +++ b/lib/std/math/hypot.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; @@ -93,14 +92,10 @@ const hypot_test_cases = .{ }; test hypot { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 try expect(hypot(0.3, 0.4) == 0.5); } test "hypot.correct" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 - inline for (.{ f16, f32, f64, f128 }) |T| { inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -110,9 +105,6 @@ test "hypot.correct" { } test "hypot.precise" { - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 - inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp inline for (hypot_test_cases) |v| { const a: T, const b: T, const c: T = v; @@ -122,7 +114,6 @@ test "hypot.precise" { } test "hypot.special" { - if (builtin.cpu.arch.isPowerPC() and builtin.mode != .debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 @setEvalBranchQuota(2000); inline for (.{ f16, f32, f64, f128 }) |T| { try expect(math.isNan(hypot(nan(T), 0.0))); diff --git a/lib/std/math/isnan.zig b/lib/std/math/isnan.zig index bf2af9be1db7472aaceae82c3d052e606ce454b7..cfbe172ecdbe22890c9e928103b328f7fe23a256 100644 --- a/lib/std/math/isnan.zig +++ b/lib/std/math/isnan.zig @@ -27,13 +27,6 @@ test isNan { } test isSignalNan { - if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest; - - if (builtin.os.tag == .windows) { - // https://codeberg.org/ziglang/zig/issues/35519 - return error.SkipZigTest; - } - inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { // TODO: Signalling NaN values get converted to quiet NaN values in // some cases where they shouldn't such that this can fail. @@ -43,6 +36,7 @@ test isSignalNan { builtin.cpu.arch != .hexagon and !builtin.cpu.arch.isMIPS32() and !builtin.cpu.arch.isPowerPC() and + !(builtin.cpu.arch.isX86() and builtin.os.tag == .windows and builtin.abi == .msvc) and // https://codeberg.org/ziglang/zig/issues/35519 builtin.zig_backend != .stage2_c) { try expect(isSignalNan(math.snan(T))); diff --git a/lib/std/math/modf.zig b/lib/std/math/modf.zig index 15515cde204a727d0191db34ace8adc68feb39e3..ea0433906958619572ad604d113f149c6fada392 100644 --- a/lib/std/math/modf.zig +++ b/lib/std/math/modf.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const math = std.math; const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; @@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type { try expectApproxEqAbs(expected_c, r.fpart, epsilon); } test "vector" { - if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return error.SkipZigTest; - if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194256 - const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 }; inline for (widths) |len| { diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig index 40429fbaab1cb7fb35a90427c69c2640ad907ed6..891ce5a397f61e2b6c655192d714e35d21f7e32c 100644 --- a/lib/std/os/linux/IoUring/test.zig +++ b/lib/std/os/linux/IoUring/test.zig @@ -1836,8 +1836,6 @@ test "accept/connect/send_zc/recv" { } test "accept_direct" { - if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30854 - try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); var ring = IoUring.init(1, 0) catch |err| switch (err) { @@ -1925,11 +1923,6 @@ test "accept_direct" { test "accept_multishot_direct" { try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); - if (builtin.cpu.arch == .riscv64) { - // https://github.com/ziglang/zig/issues/25734 - return error.SkipZigTest; - } - var ring = IoUring.init(1, 0) catch |err| switch (err) { error.SystemOutdated => return error.SkipZigTest, error.PermissionDenied => return error.SkipZigTest, diff --git a/test/behavior/align.zig b/test/behavior/align.zig index d79d2d07ba75c4660478753dc4d9a23d48fdfe2c..c9294e953b8d2c907a8b86e2c6b5916b1d75941a 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -569,7 +569,6 @@ test "sub-aligned pointer field access" { } test "alignment of zero-bit types is respected" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 964de5d20ff8754e81d3c0deae59fd44a672b6f8..d1acfb366dbfe0620409a81ef565b0902237a81b 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -1397,7 +1397,6 @@ test "allocation and looping over 3-byte integer" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag.isDarwin()) return error.SkipZigTest; // TODO try expect(@sizeOf(u24) == 4); try expect(@sizeOf([1]u24) == 4); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 697da63db23d14bb9e583745c80c8aca350d8a8d..077d3faeddc080357b48304a3f46240ad83e1fdd 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1719,7 +1719,6 @@ test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -1828,11 +1827,6 @@ test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { - // https://github.com/ziglang/zig/issues/12396 - return error.SkipZigTest; - } - const F = switch (@typeInfo(c_longdouble).float.bits) { 64 => f64, 80 => f80, diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index c3d0c0087cc7eb9694310d5f8ff3755e35ca8077..8694f366a586cd4a756f7f1acb7862c656b04f02 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -1895,7 +1895,6 @@ test "@fieldParentPtr packed union" { } test "@fieldParentPtr tagged union all zero-bit fields" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index ea01c8a88fe3ebf590d71027a7a5516cd57eeedb..583b6bf6aba3f0596a452e5f311bc1a388cd4691 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -216,7 +216,6 @@ test "vector cmp f16" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; try testCmpVector(f16); @@ -378,11 +377,6 @@ test "@sqrt f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.os.tag == .freebsd) { - // TODO https://github.com/ziglang/zig/issues/10875 - return error.SkipZigTest; - } - try testSqrt(f80); try comptime testSqrt(f80); try testSqrt(f128); @@ -943,7 +937,7 @@ test "@log2 with vectors" { builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) return error.SkipZigTest; - if (builtin.os.tag == .windows and builtin.cpu.arch == .x86) { + if (builtin.os.tag == .windows and builtin.cpu.arch == .x86 and builtin.abi == .msvc) { // https://codeberg.org/ziglang/zig/issues/35518 return error.SkipZigTest; } @@ -1411,11 +1405,6 @@ test "neg f16" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.os.tag == .freebsd) { - // TODO file issue to track this failure - return error.SkipZigTest; - } - try testNeg(f16); try comptime testNeg(f16); } diff --git a/test/behavior/threadlocal.zig b/test/behavior/threadlocal.zig index cb4480f759af537ee0824d400fda530eb21a69b7..ec1ce0b62677b9cbb4988814e4c69f94ae65548c 100644 --- a/test/behavior/threadlocal.zig +++ b/test/behavior/threadlocal.zig @@ -9,11 +9,6 @@ test "thread local variable" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag.isDarwin()) { - // Fails due to register hazards. - return error.SkipZigTest; - } - const S = struct { threadlocal var t: i32 = 1234; }; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 8ed483d02278160bc13f52b60a6b5cf5344eb40e..0ba364aabe557a0bac5832d285cc4595dc9cec25 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1609,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T { } test "reinterpret extern union" { + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isRiscv32() and builtin.link_libc) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest; + if (true) { // https://github.com/ziglang/zig/issues/19389 return error.SkipZigTest; @@ -1676,8 +1680,6 @@ test "reinterpret extern union" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO try S.doTheTest(); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 861b2e77db418adbb23343bf0a90db3733ad82f6..1b7d354e19c92996c8b6f30dde1acc2ad5914a4a 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -129,12 +129,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { - // Triggers an assertion with LLVM 18: - // https://github.com/ziglang/zig/issues/20680 - return error.SkipZigTest; - } - const S = struct { fn doTheTest(T: type) !void { var v: @Vector(4, T) = .{ 10, 20, 30, 40 }; @@ -279,7 +273,6 @@ test "array to vector with element type coercion" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; const S = struct { fn doTheTest() !void { diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig index c6571319d4fbb3a2265dd48fd31e67a9061e2055..6277c3acf6790cd769ac86dc885959e8281e7a71 100644 --- a/test/behavior/widening.zig +++ b/test/behavior/widening.zig @@ -41,7 +41,6 @@ test "float widening" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; var a: f16 = 12.34; var b: f32 = a; -- 2.54.0 From 47396c903cb118df9e5562f383026b0f460d38f6 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 27 Jul 2026 14:47:34 -0400 Subject: [PATCH 063/215] stage1: update zig1.wasm --- stage1/zig.h | 3950 +++++++++++++++++++++++++++++++++++----------- stage1/zig1.wasm | Bin 3223935 -> 3246758 bytes 2 files changed, 3019 insertions(+), 931 deletions(-) diff --git a/stage1/zig.h b/stage1/zig.h index fc2f9479bea2bf9599dfcaebe35294fed98b4db4..30e6f3f96a97f47b6648db1d1587bc75c88b6c3f 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -166,6 +166,12 @@ #endif #define zig_expand_has_builtin(b) zig_has_builtin(b) +#if defined(__has_feature) +#define zig_has_feature(feature) __has_feature(feature) +#else +#define zig_has_feature(feature) 0 +#endif + #if defined(__has_attribute) #define zig_has_attribute(attribute) __has_attribute(attribute) #else @@ -175,9 +181,9 @@ #if __STDC_VERSION__ >= 201112L #define zig_static_assert(cond, msg) _Static_assert(cond, msg) #elif zig_has_attribute(unused) -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused)) #else -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] #endif #if __STDC_VERSION__ >= 202311L @@ -193,10 +199,8 @@ #endif #if defined(zig_msvc) -#define zig_const_arr #define zig_callconv(c) __##c #else -#define zig_const_arr static const #define zig_callconv(c) __attribute__((c)) #endif @@ -267,12 +271,20 @@ #if __STDC_VERSION__ >= 202311L #define zig_align(alignment) alignas(alignment) -#elif __STDC_VERSION__ >= 201112L +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) #define zig_align(alignment) _Alignas(alignment) #else #define zig_align(alignment) zig_under_align(alignment) #endif +#if __STDC_VERSION__ >= 202311L +#define zig_alignOf(Type) alignof(Type) +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof) +#define zig_alignOf(Type) _Alignof(Type) +#else +#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type)) +#endif + #if zig_has_attribute(aligned) || defined(zig_tinyc) #define zig_align_fn(alignment) __attribute__((aligned(alignment))) #elif defined(zig_msvc) @@ -350,11 +362,9 @@ #define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ - __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) + __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol)) #endif -#define zig_mangled_tentative zig_mangled -#define zig_mangled_final zig_mangled #if defined(zig_msvc) #define zig_mangled(mangled, unmangled) ; \ zig_export(#mangled, unmangled) @@ -364,7 +374,7 @@ #else /* zig_msvc */ #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) #define zig_mangled_export(mangled, unmangled, symbol) \ - zig_mangled_final(mangled, unmangled) \ + zig_mangled(mangled, unmangled) \ zig_export(symbol, unmangled) #endif /* zig_msvc */ @@ -550,6 +560,9 @@ #define zig_noreturn #endif +#define zig_has_always 1 +#define zig_has_never 0 + #define zig_compiler_rt_abbrev_uint32_t si #define zig_compiler_rt_abbrev_int32_t si #define zig_compiler_rt_abbrev_uint64_t di @@ -560,7 +573,11 @@ #define zig_compiler_rt_abbrev_zig_f32 sf #define zig_compiler_rt_abbrev_zig_f64 df #define zig_compiler_rt_abbrev_zig_f80 xf +#ifdef zig_powerpc +#define zig_compiler_rt_abbrev_zig_f128 kf +#else #define zig_compiler_rt_abbrev_zig_f128 tf +#endif zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); @@ -645,16 +662,6 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) -#if defined(zig_ez80) -typedef unsigned int uint24_t; -typedef signed int int24_t; -#define INT24_C(c) c -#define UINT24_C(c) c##U -#endif -#define INT24_MIN (~INT24_C(0x7FFF)) -#define INT24_MAX ( INT24_C(0x7FFF)) -#define UINT24_MAX ( INT24_C(0xFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -685,17 +692,6 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) -#if defined(zig_ez80) -typedef unsigned __int48 uint48_t; -typedef signed __int48 int48_t; -#define INT48_C(c) c -/* no suffix */ -#define UINT48_C(c) ((uint48_t)(c)) -#endif -#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) -#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) -#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -726,6 +722,27 @@ typedef signed long long int64_t; #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) +#if defined(zig_ez80) + +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + +#endif + typedef size_t uintptr_t; typedef ptrdiff_t intptr_t; @@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX -#define zig_minInt_i24 INT24_MIN -#define zig_maxInt_i24 INT24_MAX -#define zig_minInt_u24 UINT24_C(0) -#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX -#define zig_minInt_i48 INT48_MIN -#define zig_maxInt_i48 INT48_MAX -#define zig_minInt_u48 UINT48_C(0) -#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) #define zig_maxInt_u64 UINT64_MAX +// zig_promoted_T implements C integral promotions except with signedness preserved, which +// allows wrapping operations to avoid the ub that would be caused by the normal promotion. + +#if INT8_MAX <= INT_MAX +typedef unsigned int zig_promoted_i8; +#elif INT8_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i8; +#elif INT8_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i8; +#else +typedef int8_t zig_promoted_i8; +#endif +#if UINT8_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u8; +#elif UINT8_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u8; +#elif UINT8_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u8; +#else +typedef uint8_t zig_promoted_u8; +#endif + +#if INT16_MAX <= INT_MAX +typedef unsigned int zig_promoted_i16; +#elif INT16_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i16; +#elif INT16_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i16; +#else +typedef int16_t zig_promoted_i16; +#endif +#if UINT16_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u16; +#elif UINT16_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u16; +#elif UINT16_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u16; +#else +typedef uint16_t zig_promoted_u16; +#endif + +#if INT32_MAX <= INT_MAX +typedef unsigned int zig_promoted_i32; +#elif INT32_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i32; +#elif INT32_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i32; +#else +typedef int32_t zig_promoted_i32; +#endif +#if UINT32_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u32; +#elif UINT32_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u32; +#elif UINT32_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u32; +#else +typedef uint32_t zig_promoted_u32; +#endif + +#if INT64_MAX <= INT_MAX +typedef unsigned int zig_promoted_i64; +#elif INT64_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i64; +#elif INT64_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i64; +#else +typedef int64_t zig_promoted_i64; +#endif +#if UINT64_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u64; +#elif UINT64_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u64; +#elif UINT64_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u64; +#else +typedef uint64_t zig_promoted_u64; +#endif + +#ifdef zig_ez80 + +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX + +#if INT24_MAX <= INT_MAX +typedef unsigned int zig_promoted_i24; +#elif INT24_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i24; +#elif INT24_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i24; +#else +typedef int24_t zig_promoted_i24; +#endif +#if UINT24_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u24; +#elif UINT24_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u24; +#elif UINT24_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u24; +#else +typedef uint24_t zig_promoted_u24; +#endif + +#if INT48_MAX <= INT_MAX +typedef unsigned int zig_promoted_i48; +#elif INT48_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i48; +#elif INT48_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i48; +#else +typedef int48_t zig_promoted_i48; +#endif +#if UINT48_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u48; +#elif UINT48_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u48; +#elif UINT48_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u48; +#else +typedef uint48_t zig_promoted_u48; +#endif + +#endif + #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) @@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w, PromotedUnsigned) \ + +#define zig_int_casts_common(bw, sw) \ + static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \ + return (uint##bw##_t)arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \ + return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \ + } \ +\ + static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \ + return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \ + ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \ + } +#define zig_int_operators(w) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t; return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \ } \ \ - static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \ - return val ^ zig_maxInt_u(w, bits); \ + static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ + return arg ^ zig_maxInt_u(w, bits); \ } \ \ - static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \ + static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \ (void)bits; \ - return ~val; \ + return ~arg; \ } \ \ - static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \ - return val & zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ - return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ - ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ - } \ -\ - static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ - return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ - } \ -\ - zig_basic_operator(uint##w##_t, div_floor_u##w, /) \ + zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ \ - static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ } \ \ - static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ } \ \ - static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ } \ \ zig_basic_operator(uint##w##_t, mod_u##w, %) \ + zig_int_casts_common(w, w) \ +\ + static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w(arg, bits); \ + } \ +\ + static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w(arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \ + } \ \ static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ int##w##_t rem = lhs % rhs; \ @@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \ + return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \ } \ \ static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \ } \ \ static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs + rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \ } \ \ static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs - rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \ } \ \ static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ + } \ +\ + static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \ + int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \ + return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \ + } \ +\ + static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ } -#if UINT8_MAX <= UINT_MAX -zig_int_helpers(8, unsigned int) -#elif UINT8_MAX <= ULONG_MAX -zig_int_helpers(8, unsigned long) -#elif UINT8_MAX <= ULLONG_MAX -zig_int_helpers(8, unsigned long long) -#else -zig_int_helpers(8, uint8_t) +zig_int_operators(8) +zig_int_operators(16) +zig_int_operators(32) +zig_int_operators(64) +#ifdef zig_ez80 +zig_int_operators(24) +zig_int_operators(48) #endif -#if UINT16_MAX <= UINT_MAX -zig_int_helpers(16, unsigned int) -#elif UINT16_MAX <= ULONG_MAX -zig_int_helpers(16, unsigned long) -#elif UINT16_MAX <= ULLONG_MAX -zig_int_helpers(16, unsigned long long) -#else -zig_int_helpers(16, uint16_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(24, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(24, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(24, unsigned long long) -#else -zig_int_helpers(24, uint24_t) -#endif -#endif -#if UINT32_MAX <= UINT_MAX -zig_int_helpers(32, unsigned int) -#elif UINT32_MAX <= ULONG_MAX -zig_int_helpers(32, unsigned long) -#elif UINT32_MAX <= ULLONG_MAX -zig_int_helpers(32, unsigned long long) -#else -zig_int_helpers(32, uint32_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(48, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(48, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(48, unsigned long long) -#else -zig_int_helpers(48, uint48_t) -#endif -#endif -#if UINT64_MAX <= UINT_MAX -zig_int_helpers(64, unsigned int) -#elif UINT64_MAX <= ULONG_MAX -zig_int_helpers(64, unsigned long) -#elif UINT64_MAX <= ULLONG_MAX -zig_int_helpers(64, unsigned long long) -#else -zig_int_helpers(64, uint64_t) + +#define zig_int_casts(bw, sw) \ + static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + zig_int_casts_common(bw, sw) +zig_int_casts(16, 8) +zig_int_casts(32, 8) +zig_int_casts(64, 8) +zig_int_casts(32, 16) +zig_int_casts(64, 16) +zig_int_casts(64, 32) +#ifdef zig_ez80 +zig_int_casts(32, 24) +zig_int_casts(48, 24) +zig_int_casts(64, 24) +zig_int_casts(64, 48) #endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_addw_u32(lhs, rhs, bits); @@ -936,19 +1107,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i32(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_addw_u64(lhs, rhs, bits); @@ -960,24 +1131,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i64(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -986,12 +1157,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1014,27 +1185,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1043,28 +1215,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1073,22 +1243,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_subw_u32(lhs, rhs, bits); @@ -1100,20 +1271,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i32(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_subw_u64(lhs, rhs, bits); @@ -1125,24 +1295,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i64(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1151,12 +1321,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1179,27 +1349,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1208,28 +1379,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1238,22 +1407,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_mulw_u32(lhs, rhs, bits); @@ -1261,8 +1431,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { + zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1271,7 +1441,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i32(full_res, bits); + *res = zig_i32_truncate_i32(full_res, bits); return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } @@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_mulw_u64(lhs, rhs, bits); @@ -1287,8 +1457,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { + zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1297,7 +1467,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i64(full_res, bits); + *res = zig_i64_truncate_i64(full_res, bits); return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } @@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1319,12 +1489,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1347,27 +1517,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1376,28 +1547,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1406,18 +1575,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif -#define zig_int_builtins(w) \ +#define zig_shls_builtins(lw, rw) \ + static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + uint##lw##_t res; \ + if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \ + } \ +\ + static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + int##lw##_t res; \ + if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \ + lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \ + } +#define zig_int_sat_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ return lhs > zig_maxInt_u(w, bits) >> rhs; \ @@ -1429,18 +1612,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \ } \ \ - static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - uint##w##_t res; \ - if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - int##w##_t res; \ - if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ - lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ - } \ + zig_shls_builtins(w, 8) \ + zig_shls_builtins(w, 16) \ + zig_shls_builtins(w, 32) \ + zig_shls_builtins(w, 64) \ \ static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ uint##w##_t res; \ @@ -1474,332 +1649,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ } -zig_int_builtins(8) -zig_int_builtins(16) +zig_int_sat_builtins(8) +zig_int_sat_builtins(16) +zig_int_sat_builtins(32) +zig_int_sat_builtins(64) #if defined(zig_ez80) -zig_int_builtins(24) +zig_int_sat_builtins(24) +zig_int_sat_builtins(48) #endif -zig_int_builtins(32) -#if defined(zig_ez80) -zig_int_builtins(48) -#endif -zig_int_builtins(64) -#define zig_builtin8(name, val) __builtin_##name(val) +#define zig_builtin8(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin8; -#define zig_builtin16(name, val) __builtin_##name(val) +#define zig_builtin16(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin16; -#if defined(zig_ez80) -#define zig_builtin24(name, val) __builtin_##name(val) -typedef unsigned int zig_Builtin24; -#endif - #if INT_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name(val) +#define zig_builtin32(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin32; #elif LONG_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name##l(val) +#define zig_builtin32(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin32; #endif -#if defined(zig_ez80) -#define zig_builtin48(name, val) __builtin_##name(val) -typedef unsigned long long zig_Builtin48; -#endif - #if INT_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name(val) +#define zig_builtin64(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin64; #elif LONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##l(val) +#define zig_builtin64(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin64; #elif LLONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##ll(val) +#define zig_builtin64(name, arg) __builtin_##name##ll(arg) typedef unsigned long long zig_Builtin64; #endif -static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { - return zig_wrap_u8(val >> (8 - bits), bits); +#if defined(zig_ez80) +#define zig_builtin24(name, arg) __builtin_##name(arg) +typedef unsigned int zig_Builtin24; +#define zig_builtin48(name, arg) __builtin_##name(arg) +typedef unsigned long long zig_Builtin48; +#endif + +static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { + return zig_u8_truncate_u8(arg >> (8 - bits), bits); } -static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); +static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bswap16) || defined(zig_gcc) - full_res = __builtin_bswap16(val); + full_res = __builtin_bswap16(arg); #else - full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); +static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bswap24) || defined(zig_gcc) - full_res = __builtin_bswap24(val); + full_res = __builtin_bswap24(arg); #else - full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) - full_res = __builtin_bswap32(val); + full_res = __builtin_bswap32(arg); #else - full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); +static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bswap48) || defined(zig_gcc) - full_res = __builtin_bswap48(val); + full_res = __builtin_bswap48(arg); #else - full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u48(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) - full_res = __builtin_bswap64(val); + full_res = __builtin_bswap64(arg); #else - full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); +static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); } -static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { +static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { uint8_t full_res; #if zig_has_builtin(bitreverse8) - full_res = __builtin_bitreverse8(val); + full_res = __builtin_bitreverse8(arg); #else static uint8_t const lut[0x10] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0; + full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0; #endif - return zig_wrap_u8(full_res >> (8 - bits), bits); + return zig_u8_truncate_u8(full_res >> (8 - bits), bits); } -static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); +static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bitreverse16) - full_res = __builtin_bitreverse16(val); + full_res = __builtin_bitreverse16(arg); #else - full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); +static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { +static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bitreverse24) - full_res = __builtin_bitreverse24(val); + full_res = __builtin_bitreverse24(arg); #else - full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) - full_res = __builtin_bitreverse32(val); + full_res = __builtin_bitreverse32(arg); #else - full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); +static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bitreverse48) - full_res = __builtin_bitreverse48(val); + full_res = __builtin_bitreverse48(arg); #else - full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u32(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) - full_res = __builtin_bitreverse64(val); + full_res = __builtin_bitreverse64(arg); #else - full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); +static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); } -#define zig_builtin_popcount_common(w) \ - static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w((uint##w##_t)val, bits); \ +#define zig_builtin_popCount_common(w) \ + static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w((uint##w##_t)arg, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - return zig_builtin##w(popcount, val); \ + return zig_builtin##w(popcount, arg); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #else -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \ + uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \ temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #endif -zig_builtin_popcount(8) -zig_builtin_popcount(16) +zig_builtin_popCount(8) +zig_builtin_popCount(16) +zig_builtin_popCount(32) +zig_builtin_popCount(64) #if defined(zig_ez80) -zig_builtin_popcount(24) +zig_builtin_popCount(24) +zig_builtin_popCount(48) #endif -zig_builtin_popcount(32) -#if defined(zig_ez80) -zig_builtin_popcount(48) -#endif -zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ - static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(ctz, val); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(ctz, arg); \ } \ \ zig_builtin_ctz_common(w) #else #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ } \ \ zig_builtin_ctz_common(w) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) -#if defined(zig_ez80) -zig_builtin_ctz(24) -#endif zig_builtin_ctz(32) -#if defined(zig_ez80) -zig_builtin_ctz(48) -#endif zig_builtin_ctz(64) +#if defined(zig_ez80) +zig_builtin_ctz(24) +zig_builtin_ctz(48) +#endif #define zig_builtin_clz_common(w) \ - static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_clz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_clz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ } \ \ zig_builtin_clz_common(w) #else #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ } \ \ zig_builtin_clz_common(w) #endif zig_builtin_clz(8) zig_builtin_clz(16) -#if defined(zig_ez80) -zig_builtin_clz(24) -#endif zig_builtin_clz(32) -#if defined(zig_ez80) -zig_builtin_clz(48) -#endif zig_builtin_clz(64) +#if defined(zig_ez80) +zig_builtin_clz(24) +zig_builtin_clz(48) +#endif /* ======================== 128-bit Integer Support ========================= */ @@ -1816,16 +1980,14 @@ zig_builtin_clz(64) typedef unsigned __int128 zig_u128; typedef signed __int128 zig_i128; -#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) -#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#define zig_hi_u128(val) ((uint64_t)((val) >> 64)) -#define zig_lo_u128(val) ((uint64_t)((val) >> 0)) -#define zig_hi_i128(val) (( int64_t)((val) >> 64)) -#define zig_lo_i128(val) ((uint64_t)((val) >> 0)) -#define zig_bitCast_u128(val) ((zig_u128)(val)) -#define zig_bitCast_i128(val) ((zig_i128)(val)) +#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) +#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) +#define zig_make_u128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) zig_init_i128(hi, lo) +#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) +#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) +#define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) +#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs > rhs) - (lhs < rhs); \ @@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128; return lhs operator rhs; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + return lhs >> rhs; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif +} + #else /* zig_has_int128 */ #if zig_little_endian -typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; -typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; #else -typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; -typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; #endif -#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) -#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) - -#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#endif -#define zig_hi_u128(val) ((val).hi) -#define zig_lo_u128(val) ((val).lo) -#define zig_hi_i128(val) ((val).hi) -#define zig_lo_i128(val) ((val).lo) -#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) -#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) +#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) +#define zig_hi_u128(arg) (arg).hi +#define zig_lo_u128(arg) (arg).lo +#define zig_hi_i128(arg) (arg).hi +#define zig_lo_i128(arg) (arg).lo #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs.hi == rhs.hi) \ @@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; + return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + #endif /* zig_has_int128 */ #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) @@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |) zig_bit_int128(u128, xor, ^) zig_bit_int128(i128, xor, ^) -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); +static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { + return (uint8_t)zig_lo_u128(arg); +} +static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { + return (uint8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { + return (int8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { + return (int8_t)zig_lo_u128(arg); +} -#if zig_has_int128 +static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { + return (uint16_t)zig_lo_u128(arg); +} +static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { + return (uint16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { + return (int16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { + return (int16_t)zig_lo_u128(arg); +} -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return val ^ zig_maxInt_u(128, bits); +static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { + return (uint32_t)zig_lo_u128(arg); +} +static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { + return (uint32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { + return (int32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { + return (int32_t)zig_lo_u128(arg); } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - (void)bits; - return ~val; +static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { + return zig_lo_u128(arg); +} +static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { + return zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { + return (int64_t)zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { + return (int64_t)zig_lo_u128(arg); +} + +static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { + return zig_make_u128(UINT8_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { + return zig_make_u128(UINT8_C(0), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { + return zig_make_i128(INT8_C(0), arg); } -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { + return zig_make_u128(UINT16_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { + return zig_make_u128(UINT16_C(0), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { + return zig_make_i128(INT16_C(0), arg); } -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - return lhs << rhs; +static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { + return zig_make_u128(UINT32_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { + return zig_make_u128(UINT32_C(0), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { + return zig_make_i128(INT32_C(0), arg); } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - // This works around a GCC miscompilation, but it has the side benefit of - // emitting better code. It is behind the `#if` because it depends on - // arithmetic right shift, which is implementation-defined in C, but should - // be guaranteed on any GCC-compatible compiler. -#if defined(zig_gnuc) - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { + return zig_make_u128(UINT64_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { + return zig_make_u128(UINT64_C(0), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { + return zig_make_i128(INT64_C(0), arg); +} + +static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { + return arg; +} +static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { +#if zig_has_int128 + return (zig_u128)arg; +#else + return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); +#endif +} +static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { + return arg; +} +static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) { +#if zig_has_int128 + return (zig_i128)arg; #else - zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); - return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; + return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); #endif } -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - return lhs << rhs; +#define zig_int128_cast_builtins(w) \ + static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ + } +zig_int128_cast_builtins(8) +zig_int128_cast_builtins(16) +zig_int128_cast_builtins(32) +zig_int128_cast_builtins(64) + +static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) { + return zig_and_u128(arg, zig_maxInt_u(128, bits)); +} +static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) { + if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg)); + int64_t lo = zig_i64_truncate_i128(arg, bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); +} + +static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) { + return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits); +} +static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) { + return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits); +} + +#if zig_has_int128 + +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + return arg ^ zig_maxInt_u(128, bits); +} + +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return ~arg; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return lhs * rhs; } -static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { return lhs / rhs; } -static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { return lhs / rhs; } @@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { #else /* zig_has_int128 */ -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; + return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; -} - -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; - return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; -} - -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; -} - -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) }; - return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; -} - -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { return res; } -zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); return __multi3(lhs, rhs); } static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs))); + return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128)); } -zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); -static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); return __udivti3(lhs, rhs); } -zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); -static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); return __divti3(lhs, rhs); } -zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); return __umodti3(lhs, rhs); } -zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); return __modti3(lhs, rhs); } #endif /* zig_has_int128 */ -#define zig_div_floor_u128 zig_div_trunc_u128 +#define zig_divFloor_u128 zig_divTrunc_u128 -static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); } -static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { zig_u128 rem = zig_rem_u128(lhs, rhs); uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) ? UINT64_C(1) : UINT64_C(0); - return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); + return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); } -static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); } #define zig_mod_u128 zig_rem_u128 @@ -2107,51 +2423,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { - return zig_and_u128(val, zig_maxInt_u(128, bits)); -} - -static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); - int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); - return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); -} - static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits); } static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits); } static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_add_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits); } static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits); } static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits); } static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } -static inline zig_u128 zig_abs_i128(zig_i128 val) { - zig_i128 tmp = zig_shr_i128(val, 127); - return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +static inline zig_u128 zig_abs_i128(zig_i128 arg) { + zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); + return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); } #if zig_has_int128 @@ -2160,7 +2466,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(add_overflow) zig_u128 full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_addw_u128(lhs, rhs, bits); @@ -2176,7 +2482,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(sub_overflow) zig_u128 full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_subw_u128(lhs, rhs, bits); @@ -2200,7 +2506,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(mul_overflow) zig_u128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_mulw_u128(lhs, rhs, bits); @@ -2216,8 +2522,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #endif } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); #if zig_has_builtin(mul_overflow) zig_i128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -2226,50 +2532,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } #else /* zig_has_int128 */ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { *res = zig_mulw_u128(lhs, rhs, bits); - return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && - zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); + return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && + zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0 || zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow; } @@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { *res = zig_shlw_i128(lhs, rhs, bits); - zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1))); + zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits); return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); } -static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { +#define zig_int128_shls_builtins(rw) \ + static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_u128 res; \ + if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \ + case 0: return zig_minInt_u(128, bits); \ + case 1: return zig_maxInt_u(128, bits); \ + default: zig_unreachable(); \ + } \ + } \ +\ + static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_i128 res; \ + if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \ + case -1: return zig_minInt_i(128, bits); \ + case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \ + case 1: return zig_maxInt_i(128, bits); \ + default: zig_unreachable(); \ + } \ + } +zig_int128_shls_builtins(8) +zig_int128_shls_builtins(16) +zig_int128_shls_builtins(32) +zig_int128_shls_builtins(64) + +static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { - case 0: return zig_make_u128(0, 0); - case 1: return zig_maxInt_u(128, bits); + case INT32_C(0): return zig_make_u128(0, 0); + case INT32_C(1): return zig_maxInt_u(128, bits); default: zig_unreachable(); } } -static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { +static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { zig_i128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { - case -1: return zig_minInt_i(128, bits); - case 0: return zig_make_i128(0, 0); - case 1: return zig_maxInt_i(128, bits); + case -INT32_C(1): return zig_minInt_i(128, bits); + case INT32_C(0): return zig_make_i128(0, 0); + case INT32_C(1): return zig_maxInt_i(128, bits); default: zig_unreachable(); } } @@ -2341,57 +2701,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); } -static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { - if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); - if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); - return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); +static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); + if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); + return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); } -static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { - return zig_clz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { + return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { - if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); - return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); +static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { + if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); + return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); } -static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { - return zig_ctz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { + return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { - return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + - zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); +static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { + return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + + zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); } -static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { - return zig_popcount_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { + return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { +static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { zig_u128 full_res; #if zig_has_builtin(bswap128) - full_res = __builtin_bswap128(val); + full_res = __builtin_bswap128(arg); #else - full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), - zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); + full_res = zig_make_u128( + zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) + ); #endif return zig_shr_u128(full_res, UINT8_C(128) - bits); } -static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } -static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { - return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), - zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), - UINT8_C(128) - bits); +static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { + return zig_shr_u128(zig_make_u128( + zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) + ), UINT8_C(128) - bits); } -static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } #if zig_has_int128 @@ -2411,12 +2774,378 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { /* ========================== Big Integer Support =========================== */ static inline uint16_t zig_int_bytes(uint16_t bits) { - uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1); uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; return (bytes + alignment - 1) / alignment * alignment; } +static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_minInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset); +#endif +} + +static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_maxInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_maxInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset); +#endif +} + +static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + + if (!is_signed) return INT8_C(0); +#if zig_little_endian + byte_offset = zig_int_bytes(bits) - 1; +#endif + return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7)); +} + +static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + uint16_t arg_size = zig_int_bytes(arg_bits); + uint16_t copy_size = zig_min_u16(res_size, arg_size); + uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8)); + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], copy_size); + memset(&res_bytes[copy_size], sign_fill, res_size - copy_size); +#else + memset(&res_bytes[0], sign_fill, res_size - copy_size); + memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size); +#endif +} + +static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + + if (res_is_signed != arg_is_signed) zig_unreachable(); + if (res_bits > arg_bits) zig_unreachable(); + + if (res_is_signed) { + uint16_t arg_byte_offset = UINT16_C(0); + +#if zig_big_endian + arg_byte_offset = zig_int_bytes(arg_bits) - res_size; +#endif + + memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size); + } else { + uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3)); + uint16_t arg_byte_offset = res_byte_offset; + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset); +#else + res_byte_offset = res_size - UINT16_C(1) - res_byte_offset; + arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset; + + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + + res_bytes[res_byte_offset] = zig_u8_truncate_u8( + arg_bytes[arg_byte_offset], + zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1) + ); + res_byte_offset += UINT16_C(1); + arg_byte_offset += UINT16_C(1); + +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset); +#else + memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset); +#endif + } +} + +#define zig_big_casts(is, s, w, IntType) \ + static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \ + } \ +\ + static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \ + } +zig_big_casts(false, u, 8, uint8_t) +zig_big_casts(true , i, 8, int8_t) +zig_big_casts(false, u, 16, uint16_t) +zig_big_casts(true , i, 16, int16_t) +zig_big_casts(false, u, 32, uint32_t) +zig_big_casts(true , i, 32, int32_t) +zig_big_casts(false, u, 64, uint64_t) +zig_big_casts(true , i, 64, int64_t) +zig_big_casts(false, u, 128, zig_u128) +zig_big_casts(true , i, 128, zig_i128) + +static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + +#if zig_big_endian + byte_offset = size - UINT16_C(1) - byte_offset; +#endif + + if (res_is_signed) { + int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset); +#endif +} + +static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int16_t lhs_cmp_limb; + int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); + if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb = rhs_byte; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; @@ -2579,6 +3308,168 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign return 0; } +static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes != 128 / CHAR_BIT || is_signed) { + zig_i128 res_limb; + zig_i128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes != 64 / CHAR_BIT || is_signed) { + int64_t res_limb; + int64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes != 32 / CHAR_BIT || is_signed) { + int32_t res_limb; + int32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes != 16 / CHAR_BIT || is_signed) { + int16_t res_limb; + int16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes != 8 / CHAR_BIT || is_signed) { + int8_t res_limb; + int8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; @@ -2816,13 +3707,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool } } +static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) { + memcpy(res, arg, remaining_bytes); + return; + } + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool overflow = true; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + +static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3248,323 +4541,755 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo return overflow; } +static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_addo_big(res, lhs, rhs, is_signed, bits); } +static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits); + + if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } +} + +static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_subo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __udivei4(res, lhs, rhs, bits); - return; - } +static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1); - zig_trap(); + if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } } -static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_div_trunc_big(res, lhs, rhs, is_signed, bits); - return; +static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t size = zig_int_bytes(bits); + uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8)); + uint16_t lhs_byte_offset = sign_byte_offset; + uint16_t lhs_end_byte_offset = UINT16_C(0); + bool overflow = false; + +#if zig_big_endian + lhs_byte_offset = size - lhs_byte_offset; + lhs_end_byte_offset = size - lhs_end_byte_offset; +#endif + + while (lhs_byte_offset != lhs_end_byte_offset) { + uint16_t rhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint16_t res_byte_offset; + uint16_t lhs_byte; + uint8_t res_byte = UINT8_C(0); + uint16_t mul_res = UINT16_C(0); + uint8_t carry = UINT8_C(0); + +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#else + rhs_byte_offset = size - rhs_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + + lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill; + +#if zig_big_endian + lhs_byte_offset += UINT16_C(1); +#endif + + res_byte_offset = lhs_byte_offset; + + while (res_byte_offset != end_byte_offset) { + bool res_byte_initialized = res_byte_offset != lhs_byte_offset; + +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); + res_byte_offset -= UINT16_C(1); +#endif + + if (res_byte_initialized) res_byte = res_bytes[res_byte_offset]; + carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8)); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16( + zig_shr_u16(mul_res, UINT8_C(8)) + ), UINT8_C(8)); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); + res_byte_offset += UINT16_C(1); +#endif + } + + while (rhs_byte_offset != end_byte_offset) { +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); +#endif + + carry = zig_addo_u8( + &res_byte, + zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))), + carry, + UINT8_C(8) + ); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + overflow |= res_byte != UINT8_C(0); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); +#endif + } + + overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0); + overflow |= carry != UINT8_C(0); } - zig_trap(); +#if zig_little_endian + sign_byte_offset -= UINT64_C(1); +#else + sign_byte_offset = size - sign_byte_offset; +#endif + + if (lhs_sign_fill != rhs_sign_fill) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(0); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8( + &res_bytes[byte_offset], + res_byte, + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (lhs_sign_fill != UINT8_C(0)) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(1); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8)); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + lhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + rhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (is_signed) { + int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + + overflow |= signed_res_byte < INT8_C(0); + } + + { + uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t fill_byte = UINT8_C(0); + + if (is_signed) { + int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + } else { + uint8_t sign_byte = res_bytes[sign_byte_offset]; + uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = truncated; + } + +#if zig_little_endian + sign_byte_offset += UINT16_C(1); + memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset); +#else + memset(&res_bytes[0], fill_byte, sign_byte_offset); +#endif + } + + return overflow; +} + +static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow } -static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - zig_trap(); +static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_mulo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __umodei4(res, lhs, rhs, bits); - return; +static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits); + + if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); } +} + +static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __divei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __udivei5(res, lhs, rhs, temp, bits); + } +} - zig_trap(); +static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __modei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __umodei5(res, lhs, rhs, temp, bits); + } } -static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_rem_big(res, lhs, rhs, is_signed, bits); - return; +static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool decrement = false; + + if (is_signed) { + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + decrement = zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32)); } + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (decrement) zig_decrement_big(res, is_signed, bits); +} - zig_trap(); +static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool increment = false; + + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + increment = zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ) > INT32_C(0); + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (increment) zig_increment_big(res, is_signed, bits); } -static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t skip_bits = remaining_bytes * 8 - bits; - uint16_t total_lz = 0; - uint16_t limb_lz; - (void)is_signed; +static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool fixup = false; -#if zig_little_endian - byte_offset = remaining_bytes; + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + if (is_signed && zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits); +} + +static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3)); + uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_prev_byte; + uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3)); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + lhs_byte_offset = size - lhs_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - while (remaining_bytes >= 128 / CHAR_BIT) { + { +#if zig_big_endian + lhs_byte_offset -= UINT16_C(1); +#endif + + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; + #if zig_little_endian - byte_offset -= 128 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); +#endif + } + + while (lhs_byte_offset != end_byte_offset) { +#if zig_big_endian + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - zig_u128 val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_prev_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 128 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 128 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 128 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 64 / CHAR_BIT) { -#if zig_little_endian - byte_offset -= 64 / CHAR_BIT; + { + uint8_t lhs_sign_fill = UINT8_C(0); + +#if zig_big_endian + res_byte_offset -= UINT16_C(1); #endif - { - uint64_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift); } - total_lz += limb_lz; - if (limb_lz < 64 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 64 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 64 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], lhs_sign_fill, res_byte_offset); #endif } +} + +static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t lhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3)); + uint8_t lhs_prev_byte = lhs_sign_fill; + uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3)); + bool overflow = false; - while (remaining_bytes >= 32 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 32 / CHAR_BIT; + lhs_byte_offset = size - lhs_byte_offset; +#else + res_byte_offset = size - res_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint32_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); - } + while (lhs_byte_offset != end_byte_offset) { +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#endif - total_lz += limb_lz; - if (limb_lz < 32 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 32 / CHAR_BIT; + overflow |= lhs_prev_byte != lhs_sign_fill; + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; #if zig_big_endian - byte_offset += 32 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 16 / CHAR_BIT; + end_byte_offset = UINT16_C(0); +#else + end_byte_offset = size; +#endif + + { + bool lhs_more_bytes = lhs_byte_offset != end_byte_offset; + +#if zig_little_endian + if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t lhs_byte = UINT8_C(0); + + if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset]; + + if (is_signed) { + int16_t shifted = zig_shr_i16(zig_or_i16( + zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_i16_intCast_u8(lhs_byte) + ), byte_shift); + int8_t truncated = zig_i8_truncate_i16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + + overflow |= zig_i16_intCast_i8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif + res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + } else { + uint16_t shifted = zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift); + uint8_t truncated = zig_u8_truncate_u16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + + overflow |= zig_u16_intCast_u8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + res_bytes[res_byte_offset] = truncated; + } - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 16 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_big_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + while (lhs_byte_offset != end_byte_offset) { #if zig_little_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - uint8_t val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 8 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_big_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - return total_lz; -} + { +#if zig_little_endian + res_byte_offset -= UINT16_C(1); +#endif -static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t total_tz = 0; - uint16_t limb_tz; - (void)is_signed; + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + byte_shift + )); #if zig_big_endian - byte_offset = remaining_bytes; + res_byte_offset += UINT16_C(1); #endif + } - while (remaining_bytes >= 128 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 128 / CHAR_BIT; +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#else + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); #endif - { - zig_u128 val_limb; + return overflow; +} - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u128(val_limb, 128); - } +static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits +} - total_tz += limb_tz; - if (limb_tz < 128) return total_tz; - remaining_bytes -= 128 / CHAR_BIT; +static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + (void)zig_shlo_big(res, lhs, rhs, is_signed, bits); +} -#if zig_little_endian - byte_offset += 128 / CHAR_BIT; -#endif +#define zig_big_shls_builtin(w) \ + static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + uint##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \ + } \ +\ + static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + int##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ + lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \ + } \ +\ + static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \ + const uint8_t *lhs_bytes = lhs; \ + if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \ + switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \ + case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \ + case INT32_C(0): return zig_minInt_big(res, false, bits); \ + case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \ + default: zig_unreachable(); \ + } \ } +zig_big_shls_builtin(8) +zig_big_shls_builtin(16) +zig_big_shls_builtin(32) +zig_big_shls_builtin(64) + +static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = bits / CHAR_BIT; + uint16_t end_byte_offset = UINT16_C(1); + uint16_t size = zig_int_bytes(bits); - while (remaining_bytes >= 64 / CHAR_BIT) { #if zig_big_endian - byte_offset -= 64 / CHAR_BIT; + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint64_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u64(val_limb, 64); - } + while (arg_byte_offset != end_byte_offset) { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); +#endif - total_tz += limb_tz; - if (limb_tz < 64) return total_tz; - remaining_bytes -= 64 / CHAR_BIT; + res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset]; #if zig_little_endian - byte_offset += 64 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 32 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 32 / CHAR_BIT; + { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); #endif { - uint32_t val_limb; + uint8_t byte = arg_bytes[arg_byte_offset]; + uint8_t fill = is_signed + ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) + : UINT8_C(0); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u32(val_limb, 32); + res_bytes[res_byte_offset] = byte; + +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif } + } +} - total_tz += limb_tz; - if (limb_tz < 32) return total_tz; - remaining_bytes -= 32 / CHAR_BIT; +static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t end_byte_offset = UINT16_C(0); + uint8_t arg_prev_byte; + uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + { #if zig_little_endian - byte_offset += 32 / CHAR_BIT; + arg_byte_offset -= UINT16_C(1); +#endif + + arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); + +#if zig_big_endian + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { + while (arg_byte_offset != end_byte_offset) { #if zig_big_endian - byte_offset -= 16 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); +#else + arg_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u16(val_limb, 16); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), + zig_u16_intCast_u8(arg_prev_byte) + ), byte_shift)); + arg_prev_byte = arg_byte; } - total_tz += limb_tz; - if (limb_tz < 16) return total_tz; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_little_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + { + uint8_t arg_sign_fill = UINT8_C(0); + #if zig_big_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); #endif - { - uint8_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u8(val_limb, 8); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift); } - total_tz += limb_tz; - if (limb_tz < 8) return total_tz; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_little_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], arg_sign_fill, res_byte_offset); #endif } - - return total_tz; } -static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; +static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); uint16_t total_pc = 0; (void)is_signed; #if zig_big_endian - byte_offset = remaining_bytes; + byte_offset = zig_int_bytes(bits); #endif while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 128 / CHAR_BIT; #endif { - zig_u128 val_limb; + zig_u128 arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u128(val_limb, 128); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 128 / CHAR_BIT; @@ -3575,15 +5300,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 64 / CHAR_BIT; #endif { - uint64_t val_limb; + uint64_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u64(val_limb, 64); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 64 / CHAR_BIT; @@ -3594,15 +5321,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 32 / CHAR_BIT; #endif { - uint32_t val_limb; + uint32_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u32(val_limb, 32); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 32 / CHAR_BIT; @@ -3613,15 +5342,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 16 / CHAR_BIT; #endif { - uint16_t val_limb; + uint16_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u16(val_limb, 16); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 16 / CHAR_BIT; @@ -3632,15 +5363,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 8 / CHAR_BIT; #endif { - uint8_t val_limb; + uint8_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u8(val_limb, 8); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 8 / CHAR_BIT; @@ -3653,6 +5386,274 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ return total_pc; } +static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = UINT16_C(0); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + uint16_t total_tz = UINT16_C(0); + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits); +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t remaining_bytes = byte_offset; + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool sign_limb = true; + uint16_t total_lz = UINT16_C(0); + uint16_t limb_lz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits) - remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + /* ========================= Floating Point Support ========================= */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ @@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input); #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) #else -#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) -#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) -#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) -#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) -#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) +#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) +#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) +#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) +#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) +#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) #endif #define zig_has_f16 1 #define zig_libc_name_f16(name) __##name##h #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) -#if FLT_MANT_DIG == 11 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f -#elif DBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 typedef double zig_f16; #define zig_make_f16(fp, repr) fp -#elif LDBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 -#elif defined(__SIZEOF_FP16__) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__) typedef __fp16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #else @@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16; #undef zig_init_special_f16 #define zig_init_special_f16(sign, name, arg, repr) repr #endif -#if defined(zig_darwin) && defined(zig_x86) -typedef uint16_t zig_compiler_rt_f16; -#else -typedef zig_f16 zig_compiler_rt_f16; -#endif #define zig_has_f32 1 #define zig_libc_name_f32(name) name##f @@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16; #else #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 24 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 typedef float zig_f32; #define zig_make_f32(fp, repr) fp##f -#elif DBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 typedef double zig_f32; #define zig_make_f32(fp, repr) fp -#elif LDBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l -#elif FLT32_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 typedef _Float32 zig_f32; #define zig_make_f32(fp, repr) fp##f32 #else @@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32; #else #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 53 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_make_f64(fp, repr) fp##f -#elif DBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 typedef double zig_f64; #define zig_make_f64(fp, repr) fp -#elif LDBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l -#elif FLT64_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 typedef _Float64 zig_f64; #define zig_make_f64(fp, repr) fp##f64 -#elif FLT32X_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 typedef _Float32x zig_f64; #define zig_make_f64(fp, repr) fp##f32x #else @@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64; #define zig_has_f80 1 #define zig_libc_name_f80(name) __##name##x #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) -#if FLT_MANT_DIG == 64 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI +#undef zig_has_f80 +typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80; +#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent } +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#define zig_mantissa_repr_f80(arg) (arg).mantissa +#define zig_exponent_repr_f80(arg) (arg).exponent +#elif FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f #elif DBL_MANT_DIG == 64 @@ -3818,68 +5821,91 @@ typedef __float80 zig_f80; #define zig_make_f80(fp, repr) fp##l #else #undef zig_has_f80 -#define zig_has_f80 0 -#define zig_repr_f80 u128 typedef zig_u128 zig_f80; +#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa) +#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa) +#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg) +#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg) +#endif +#ifndef zig_has_f80 +#define zig_has_f80 0 #define zig_make_f80(fp, repr) repr +#ifndef zig_make_repr_f80 +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#endif #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr #undef zig_init_special_f80 #define zig_init_special_f80(sign, name, arg, repr) repr #endif -#if defined(zig_gcc) && defined(zig_x86) -#define zig_f128_has_miscompilations 1 -#else -#define zig_f128_has_miscompilations 0 -#endif - #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI +#undef zig_has_f128 +#if zig_little_endian +typedef struct { uint64_t lo, hi; } zig_f128; +#else +typedef struct { uint64_t hi, lo; } zig_f128; +#endif +#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_lo_repr_f128(arg) (arg).lo +#define zig_hi_repr_f128(arg) (arg).hi +#elif FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 +#elif DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 +#elif LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 +#elif FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 +#elif FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) +#elif defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) #else #undef zig_has_f128 -#define zig_has_f128 0 -#undef zig_make_special_f128 -#undef zig_init_special_f128 -#if defined(zig_darwin) || defined(zig_aarch64) -typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; -zig_basic_operator(zig_v2u64, xor_v2u64, ^) -#define zig_repr_f128 v2u64 -typedef zig_v2u64 zig_f128; -#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } -#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 -#define zig_make_f128(fp, repr) zig_make_f128_##repr -#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr -#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr +#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) +#if defined(zig_msvc) && !defined(__clang__) +#include +typedef __m128i zig_f128; +#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } +#define zig_lo_repr_f128(arg) (arg).m128i_u64[0] +#define zig_hi_repr_f128(arg) (arg).m128i_u64[1] +#else +typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; +#define zig_init_repr_f128(hi, lo) { lo, hi } +#define zig_lo_repr_f128(arg) (arg)[0] +#define zig_hi_repr_f128(arg) (arg)[1] +#endif #else -#define zig_repr_f128 u128 typedef zig_u128 zig_f128; +#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo) +#define zig_lo_repr_f128(arg) zig_lo_u128(arg) +#define zig_hi_repr_f128(arg) zig_hi_u128(arg) +#endif +#endif +#ifndef zig_has_f128 +#define zig_has_f128 0 #define zig_make_f128(fp, repr) repr +#ifndef zig_make_repr_f128 +#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo) +#endif +#undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 #define zig_init_special_f128(sign, name, arg, repr) repr #endif -#endif #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) /* Emulate msvc abi on a gnu compiler */ @@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble; typedef long double zig_c_longdouble; #endif -#define zig_bitCast_float(Type, ReprType) \ - static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ - zig_##Type result; \ - memcpy(&result, &repr, sizeof(result)); \ - return result; \ +#if __AVR__ +typedef signed char zig_FloatCompareResult; +#elif defined(zig_aarch64) +typedef signed int zig_FloatCompareResult; +#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ +typedef signed long zig_FloatCompareResult; +#else +typedef signed long long zig_FloatCompareResult; +#endif + +#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \ + static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \ + UnsignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_u##iw##_truncate_u##iw(res, w); \ + } \ + static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \ + SignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_i##iw##_truncate_i##iw(res, w); \ + } +zig_bitCast_float(16, 16, uint16_t, int16_t) +zig_bitCast_float(32, 32, uint32_t, int32_t) +zig_bitCast_float(64, 64, uint64_t, int64_t) +#if zig_has_f80 +zig_bitCast_float(80, 128, zig_u128, zig_i128) +#else +static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg)); +} +static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) { + return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) { + return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +#endif +static inline zig_f80 zig_f80_bitCast_big(const void *arg) { + return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80))); +} +static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) { + if (res_is_signed) { + zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits); + } else { + zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits); } -zig_bitCast_float(f16, uint16_t) -zig_bitCast_float(f32, uint32_t) -zig_bitCast_float(f64, uint64_t) -zig_bitCast_float(f80, zig_u128) -zig_bitCast_float(f128, zig_u128) +} +#if zig_has_f128 +zig_bitCast_float(128, 128, zig_u128, zig_i128) +#else +static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg)); +} +static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) { + return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) { + return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +#endif -#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ - zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ +#define zig_convert_float_00(ResType, operation, ArgType, version) \ + zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ + return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) +#define zig_convert_float_01(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_10(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_11(ResType, operation, ArgType, version) \ + return (ResType)arg +#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ - ResType res; \ - ExternResType extern_res; \ - ExternArgType extern_arg; \ - memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ - extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ - memcpy(&res, &extern_res, sizeof(res)); \ - return extern_res; \ + zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ + zig_has_##arg_when)(ResType, operation, ArgType, version); \ } -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) -#ifdef __ARM_EABI__ +#define zig_convert_floats(SmallType, BigType) \ + zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ + zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) +zig_convert_floats(f16, f32) +zig_convert_floats(f16, f64) +zig_convert_floats(f16, f80) +zig_convert_floats(f16, f128) +zig_convert_floats(f32, f64) +zig_convert_floats(f32, f80) +zig_convert_floats(f32, f128) +zig_convert_floats(f64, f80) +zig_convert_floats(f64, f128) +zig_convert_floats(f80, f128) -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); -static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); -static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } - -#else /* __ARM_EABI__ */ - -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) - -#endif /* __ARM_EABI__ */ - -#define zig_float_negate_builtin_0(w, c, sb) \ - zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) -#define zig_float_negate_builtin_1(w, c, sb) -arg -#define zig_float_negate_builtin(w, c, sb) \ +#define zig_float_negate_builtin_0(w, sb) \ + zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) +#define zig_float_negate_builtin_1(w, sb) -arg +#define zig_float_negate_builtin(w, sb) \ static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \ - return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \ + return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \ } -zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) -zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) -zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) -zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) -zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) +zig_float_negate_builtin(16, UINT16_C(1) << 15) +zig_float_negate_builtin(32, UINT32_C(1) << 31) +zig_float_negate_builtin(64, UINT64_C(1) << 63) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) +zig_float_negate_builtin(80, UINT16_C(1) << 15) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg)) +zig_float_negate_builtin(128, UINT64_C(1) << 63) #define zig_float_less_builtin_0(Type, operation) \ - zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \ + zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \ zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ + return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ } #define zig_float_less_builtin_1(Type, operation) \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -3994,13 +6077,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) return lhs operator rhs; \ } +#define zig_float_builtins(w) \ + zig_common_float_builtins(w) \ + zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \ + zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, ) #define zig_common_float_builtins(w) \ - zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ + zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \ @@ -4031,82 +6153,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \ zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \ \ - static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ - return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \ + return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \ } -zig_common_float_builtins(16) -zig_common_float_builtins(32) -zig_common_float_builtins(64) -zig_common_float_builtins(80) -zig_common_float_builtins(128) - -#define zig_float_builtins(w) \ - zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) zig_float_builtins(16) -zig_float_builtins(80) -zig_float_builtins(128) - -#ifdef __ARM_EABI__ - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); -static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); -static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); -static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); -static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); -static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); -static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); -static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); -static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); -static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); -static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); -static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); -static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } - -#else /* __ARM_EABI__ */ - zig_float_builtins(32) zig_float_builtins(64) - -#endif /* __ARM_EABI__ */ +zig_float_builtins(80) +#if defined(zig_x86_32) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_f128 arg); + return __floattitf(zig_f128_bitCast_i128(arg)); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(zig_f128 arg); + return __floatuntitf(zig_f128_bitCast_u128(arg)); +} +#elif defined(zig_x86_64) && defined(zig_windows) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_i128 arg); + return __floattitf(arg); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi); + return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg)); +} +#else +zig_float_builtins(128) +#endif /* ============================ Atomics Support ============================= */ @@ -4410,19 +6498,19 @@ typedef int zig_memory_order; } \ static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ - } \ + } \ static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } zig_msvc_atomics( u8, uint8_t, char, 8, 8) @@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } \ static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } @@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) { - void* val = (void*)__iso_volatile_load32(obj); + void* value = (void*)__iso_volatile_load32(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { @@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) { - void* val = (void*)__iso_volatile_load64(obj); + void* value = (void*)__iso_volatile_load64(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) { diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 1664bd4095df86103a6e4bacfc682054a0cb8fc1..8587696fd79e5f385e8ea9fcf56614213bcce485 100644 GIT binary patch delta 934419 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⁡t(S}!kO9?41Ks*%I< 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

?R+U9Bx>%N{n`FA|_8ow`wE5=8Wvo2?D{ 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 NZegOU!(Ti6zW~KQF&6*; delta 911066 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%0Dl>H4UsjM;8 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%0A(pHUzF0rVFo=sjC@R2 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

h~M<#l(8-@WtzzLfPfj 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

p`u3 zO~1l;V^YMEQsk&e4Hk>c1rn7GsoBd~5?$y%<3k)`xgI2?G{@{X261cWvRiVx!fm1jP=iNV z6vw;t{1;`hU6io9d%}M*=cVj0sM-)pOBF_9oDfOyFITZ@y+|&fl8Z;(o)0Y#sRm#k zWdy4$_QEul;uH`9rWz>~@IkSJa+OAsHUbCNnz3K_y#_U;w6czTP^XPNmqyA;PlxoI zKM=sfihdo?P5+6X1VDO!i(wgVa$4(wl0^Zf)mCRnPhA1?PP#ChEcYIxI{=~ zc4bDHwUQjAR9CbWBG`!f^J+tvQ%xzhWP0`y^R~cPusUP?-)$0r+tWL@3plC0) zZ8Gjs+tvhx1i##e2^bR@(*wlph-PLdM>+puXZLW=MJ+XQw(xCblbWINd{h1lle{zn zy_q|qhIY6gsib(3w(6YQsbi{~kmsUIi=_t%hT#ImwR|YRkWf&GBSgqP%3@jo7Mm&s zXc)w^0)^FFkVsX(UkuqOGBz?65s)w2_Jog3i|0^6Sn0p-Bm|jQoYWtHKEirt7g%8* ztrE+G^wBQT^rj)|h+)aiN~H_AwUf4FrB_Vzugp;pZ%d}pS-%U@=p0Xdbcl%(r30)h z&#W9yeUi#RBX%XmT38)Ek=px;KjfKkqw!S@sc$KSXy39%+JG)Kl7@?@|GmMMS_jE6%MR{%X^Ob8a1pbv zbTj(+d5FRZQOpt)E5b@tfT1eHP!5Jl!BD9fb^=4aB~FPYPFjdzLrF;@S|D!i zN|qAHQew%{N;I`L@mJ zZ%t_hPlg|?<%5X^3lpv3i*@9K6(uQ}YC56zT4bxEKn{u2X=Qe$GLLCxnq%4?_ZcPW zni%vDuYLJ^3o&%o$82MoV=Vf}2dyj@qOm_xez|Q-tSlki5+Yb32pU2J4IpR=5!8X8 zQ4lmL0*t`%U>4KY-Lp++#&D2DyO@Q7kawE4+Cu_!kC zppat;f}-7L=OaYXM!>srK~b(K_6LP!`DTm3z0p!Z%0HH*0_E4UH!GapO!-#wK`V!k zqOk)gU+3h>enXpQtKbB)xiZULp?EfX;8~umhetg^JZ*$-E*CuIisumUJY;*L1I@xG zrzFv=5j1iDLpudD>)CzQ>VT%zlfzN19CnJv4h7GHwpT(tX{ps&A$T4M@ic&^Da2C; zo<{OPqoO$sG!NLm=|GcGooYcNM?|!PK$EBq@l=ARM)1@qp7G#WW}7w8QYY#@WeGeG z6mr}|TQrasv9GQzl6bJ>gH}#uMPo;TVX19Uhyekv7*+^|hb#tmAwkg;qNtPTvx1^g zQ5*#dk#UT)5QP(>s1_6tCffmq+7Lq}7-|GVjbb<&4EHI9HbU@-U`z`!Y#soH2ORoe z8EpU^9HM9&KnDwoaz$|rC~7SwLKN?PUtZ)sX^A0NmL-V+lJz(rC^10NNi42Bpc9=2889?`q2O>U#{g(q5L8{{+qiX zSR)AT4iU6~U_CoH+NB_9mED|H4gp4Er-GnHDxgDYC~%=7BhtQA6q#04WF`Q&P%B#A zS1T$PZbXH$JzBv4NMPKH$5NUZ|<}^WCsYoY+^iD=*gJph*Wj%X~?cu&sD|?G=vai&p`$|`V zWv*hW46!)weOixd!B7=qr~*T6h@lb;HG-i=F;bJg}D5zn9)})?4rK}L(4f5MMOJof< z&&j_|mGqwaefQlS$iHo!4Lx~xTapCa5!l`{9H2cR0r{YfFdq4&9K^y0Xqp=$W!z{(nUTFJKLIm8S)tD+sD$OcE%;Tq1xsnF9eFdXoTF*gCTL zAag8N403m(d$+Boz|JzW1@>lvz0p>)1NKg=G%mgr3K5ygd)3&_E^ydx!e2_ zvygI$rBdz!Dc87lxu0isDYr_>U2G?tCag)^=%MOdV-CWee9%mUfM{%)pgdnt)@+UP zse2e%=^a(cTqZatnSG0B!vj+AJSkYdb-~Y`gZ(?(FiXl^WU8dxgHmpywmo~Rwr{S$ ziqu(d16LIkTxh!jQxQtoVRAJGT9=-g?+jo*nR=^*F^ER_Wl z%`SZ@_o$ScpzYhb++VRcq?B7F<;u(qDYsn8ou%#Dy4(%F>JhahFD;XD=b8_t++$Mi zOl{xREWl3*@X1=|5V*DL{IN=aPd8r*@CpGwN$VT} zulS(LWV1|wPcu6V0QhMEK2hr&0@rs1<_fE5!KvnIfVY1}fd8y@mdHq5mvO5eq53H- zg)2hADdr9N$g@)J1g*X;7t9nHA;8w&yGnphHhl&H+$g}uYxP6mhh_AODZ~OV6X27~ z$pZYG03WB-4}m|B5zjHw5O|gVpJ?s@IPtsyA1lBOM21VJ0Ub-*G<6&bR`49>NvxQ- zzD7yxIaaoAkdRT^P1B_6B8zNoHbmtER=ll`q6S8-cx#QK29gijq9WdQi>D8_-);=? zd~Ijjxz)nqNkg?D`?I;oi^YeIp|ZzFWvjvhi$9_lJ88B=U{5ghz;6G7wCrdBmY7~$ zI)<_SS(h<1RmvT2xcM_aYNeDrO3Jm^a=}jzsQFxGppIIt!(F7{ICH#|cu`6msWc2r zd~m;(kg2Gn#7Ze~tf`d}FG&dwZPAdh#3uUS(iT45%i78n1N^p+<&K>l~ntGFJgL@D+hNOrRwG9=Jlg>!pAkY3gG! zZ{QmOa%i6Q?_*zkc;w2GwB!{}CU#V85GR&}v~0cTYjJ38%98C9JifMMldIX#bkz0>I|7-5`4WBt!=3QsT8U~*{;^Ht;8>>{9(~Lym{3+Fxpf8A|Ky@Q5yrtdPyOTUd%s$C%6cqinn1! z=>?h%2db?H9&cCv(}*K|bcVP-{|4f2TL;AT`L_{wGGY0TAnw>AJ?R~!?>*+j+TzSo z#F{W<&kcNnpBW6tM88YCJT)UyT#m>37~l!MJou=&%AxbX(-;m1#CJJ-;Kc%RZd)6~ zB@9;7K<6RDSCbiXIFR~9$P$eJ0@#({|7*Z;1)OF{9B%W3i<3N>x6q?QXl>&1YimRX z?9{e6!!USYa!Va_Bs%UH>VlSeIDy~g`OtK%hr&IQ)FP+hiV!>2!^8uiwYl{)WYH*r z`@{=*CKKLJ={e}JwJ%l{yor*nBbj=ahbv5ze|-^*a5gjwze&JCFRA!L*&Xl`eAgqHi>Yw5x{D;^f(H3@iXT+>D?j?0-KT zP=x}R!oUPEOza$EquYNjqNr(AX9QatemiaA+8zqgak!q|Y#)9ea!0!SPgpqEvYSd0 zONbFG0NuTL9sI=|xfir1v5J&sjAYnrnB&nn9-QZV^y1~!D!KBSmy=^Hz54Kq-~VZl zeTbEzG=*Co34)w_l-lsoR6ef9V+kI=T`FJScE9e1$sJ#j2E@t3*A;hO%EveHNHLC| z$V}m|nGZ}eNP{5F+yws(zP|2$y?l=}gG3xohVA^xw1abE4iyNLe8nw!r)dYt1f-oS z3^+Il@35E84LED@$Y$o7W?sT$0Ulp9k2ogn;6e;%@)CgovDNaGj(&8MdBOdBg#i)g zI^;9eL3~Dtzf^w8RDKqZ?3kJ*z9I_ADZ`^SU?EyV>b`V`pap@&Quou_q$k8>I8@qD z4?&&=yGy2J_>2G$(QNS(ac%PH6Vv45c;wKQtd%xayN@#rwjaYI4GyUHD1OqQfS-@x zXDRA@_lA7IVK8}|wN4%%av$F`Uk^qUgna(kJR^+3NuctbZ%c;=NpQO0@fP!l_yVUI zk9VyRDnYD(K(|Ow-`DPy`3wdi^beo8gIvnaQkanN2nV=?Y2YUu*@B=q4T9j87TXuT zz_l!2-Zx+1A(n=3GgAmpuh_6qa2b9wZwY?F>*{baF54voyCZ{V((KL;1vvOaMhyo5hrz;9ydcEKq z?m0nO=B4}Pc_E&8RbcBbX&TNmLC3Ck=@>pTCyK9EY?rU_Zb{+y%#wg#O5m7tr4)us z$>9)h+a`tK43e*RnMb&Br0$ouO275+$2cjJe%4SY+$sX*Tjmiy5}D|S|Ev$&&+e0< zrwdqwt3WVMZyFw9_IGf_s51)=J3L;4M~;R2Vm!hs?{I64pRlhx+@0em4CM|t`1lEv zx7Y~qa|V90DoqV|goWCnwE{n3gLdLPd`GJXo?&Vh1k!kdM;MeHZVK@e_G0-$a||9~ z5|$=u*1;pJzVelZBRs;cE1*BPOrW|9kKDrG3#_<88F!dPbtxW`?0@==QW8d4!P^UF zp=J#2z4^V={e!{UDpU3MW-g!KA@Kap)ceRVhu@ld%UT6OC`GI=lq+ z*#8F8;jc`^CrzUln~Lj9qrWsWzWovD@S-B80`=}P-!3%uzBSZvftkn8%+n-8v0Kg4 z`GyjvJtaf>MUnIT1N!H~?BdLO-tXblwQs;OJlD2cD5nGC*}(16HUAKnx~(; zh`UePJ2(?IDMikfMI25BRtYB`7@cY4 z%t_|y^;f0XiH5wUEEbqgFwNg*O8&PQ!8Omw0Dfqm78;rIU#4FB`?6+^H*J3Nl|22x zP~r!MM`eyPMXBs!JjWVzKJ$t^9b+c@3Pjo9+tEc%4FG*}p-jV3rkO|YlJ1W*TzQ45 zcZ3l;e==A(yvXT+dY>5l9cD_tVX$&2NS%$YHjPdwaw_rEZkjp7C4AG&cmvvc)6Bu9 z-pk*~`WX-qdnJB@JK$Bb}}S(Aee^0lFoK}Ak4^zfK@YBBZhGD2mb%Y7v1`h)uT(UDTVWT?^!?zbQG{bl=Z> zTlts}VqcPMCeOL*b0MKRGu{{BvPPqQ45Z5qzfPNGZg@?|QWZH>7}K(LdBRPkeER-9 zd8#!e`<4+Nz0K37h$BLqz0CS~4hBd(;o@5;Wf|wqFQvmCW|2Jhyo?YD`zefXGf&+N zN}o0*YYb?M4C}5oCFh!_D$`2a6Vhg-S(J|$)v3bZ_gX_2<>o0f?NcdQW*#4XMPMs6 zTHWW@%D0qT(GVi;tt1DYX`XO3FDYn&(Hct3Qv3T$(n_&mT$4?QMFzCZqJ$S08UkLV zKN@M5WTwp#OESxNJmuFV$+XjfFnV$QMz(|;;Kinn&#?899&3ucQdJo+s-=bzo ze_)8(Dss93+=oS9D8l9)7nzTbmyU6^ZkSQ63LUxP6W%O6ZIs=Fqu50fR{t#RBB5g= zM`PE7^V-hZ#ms;Qo0-{P;?)<8yw)BlRL1Z zvNnuN18>YTa({;(N85_M;+nMCE7H=oIxQh{a@qiOID|Ebqg`i;;4_?H`0cFkJd73< zoV95hkQLB%DA1K!T?QN6k@(dd*~wctiX3D}D?Xh2{p)!Rd~s@jJQK5Y=Ja|enU?_+C!p6SP< z+;)J@$9s@HMNkg*K#`|$VNllTGsoC<{@G!HCtVTFEOQVLis%;@2aGWcB$QwfJ+%a#G+8aUsC?L7L$LaGNdq5A|_~M;-v49w2CW#v& zfTe@<`8$wl_gTkI72u=~Z&F;gPXEoZ>yGC_;KApoF+Q%eDPl`z!YHgd_xHp2-Rk~c z)x=yPy9XFrY{!>f17fiDxYlY0P&}be8f%X~7JS59+2|WKnD>mQUOa0|kt#$6&GNZroAC}JihX7r%{aTFSQ66m?&vTC(Brp-+%xzq49w75 zK?)ayNZvwZz-mM{mQ#E-&i;_r);2oUMH6v_xQdb3kttASCN{znyAOF0=RmUcm~)%s zKy$e{^#F^oE!ZUkn_3A=hK*b(6{0|X-NU7v3YZ_>fp&uPz$`QKEtJV47dfpM3(`_a z@|N71V{>Za+4+>Mhgd7igijl@%w6u8WKi|kBA(5z9)h7b*R#_u0bmZQMnZt$Ib78- z3*zd7?Z$)1h7I|~fcNN_D5$wPvU`9`Z#=;Kt^snhJLoQM+$>D&fJhNUkLhm?wtHmE zTI3b4U71qfG%9{V%jG&k2jn`K^Szqsgl(WQR%U2!$T@On(UkNKC!aw^$ztIt%wZz1 zpo6f=4f6-@N9jexT<9=3F<1VNF!#-PyH|9K>x*bP#7^+&SMIr2o>I$7$1obBhT~zc zqsDi!lEY1eIS(Z{8x0uS=<5t+6(23+>kV8|p0U{Fb5Sfr1g2Q{NGwa`9z#c|5S0^7 zEHj>GnQMfsr2cB7kZlu5dH^Kp0j{8t+10 ze5L_wc|foSW(|o`$x^wnqErZ0^drgjRb?TA3O3XmfJo4n_pE$$qws<&Hb@mV3e@4e#i54s)0<*p zv4~<$ZZ>j45$_;EMDQ3o5=LiOJJ>gE_`*X&xog<$6PcWJETtUiKCedyJTo{O}_7;!q{=eN8m=Xgsx>+9PIMNCRnmOvtSub|m1r zjiekx#z?`LN6MUcys3|#0PfQ%PI$e6aC{a*mMV8iW$}GEIX;Su8}xH7yL!%#Q zMo$OD7I*ZLGJ~VvD5D>R(GLT$>q$FmEAp7h26U~DIoz&fil*>79noR(M*x6amNh~q zDh~bU4aDLYZJFi5JPR#_U>p(5(7MnJt?fr3*9wpa0?4866yx$>U3|2i5=lqVmcu@?Bpv*j|4`E5yD#ao*yr#LtYCP~3KB`jmm7(wkU+#c@ZCTU zW0|cld)ZseGBeGG*)B`vN*I(1Ek2ILWshsH-f$wv@W<6$e5+;gjmF~JH>?ei_hmCk zQ4YKeW+EYnbzm05a)wGy$ajn0&K@b=L9qx%$}+21#@kUHEfvFq7#0j-RfvPMa}4b= zhA|k!K6_ah{}Kb~Mqb%*DNJ#b*8_1)|2E=ICM^FE#0?3@ zJ+--JK3>klovz6e8Mf-|3zR_n&Q9o%`mn?4}-ctE_E=HPFkau-BAo`wDX_aMm-~VUQILZTNg&>;&PAh5HIyd(#gz)10$U z*$$bKC%HQ>gQm;5gXu_yiZNwL-+j;*_6OJzn9U0&HEZvM@BS=gNncikZ3-JyjGg&} z+;sm?#JQ`1@j5$qC1$LHcDt`=w|S67LGBKg3v0JIGYh7G)&(X*Fp?R_SZ?;|q>Fvr z^3=YAeHKfGJ3*al=EmY>Qf)M+F{m&e&sTi zjHLN4X%2g;~GK-E8I+~UUO+;btM6~Q}A_j6I&dHhy14iyl5R}}R zK*`Wd5CQH)%neOM8z-VoCgKQ8M7>!$e>@#ahhp5{oHNh6!8$O8v3V?8a^BH31(w~` zhz~p|0EwTaNYQ0QdCqE*H5q^)eKXu4k|>P9`7nn1`QUk#!tU59(M%K$79f!M{hOQu zTuv6XB2*AjQN$?f83766NVVd`n|GAP-zP~nP81h`iWOc&*H|3qwx|EZuC03w+6s}f zx}O`=KZp&I0kFZBaNGbTpZ|&7)4zZhlj|pW6fs7_cXldGI{tG_nM6?BjS>K&BuKz` z1I_XyPK9nlw>`2QPXiIhHo6MUCz}N53<8+$CMseOKr0g!wMwF*V=dS>dRUndoCw4M{bZr);vSsu8X ziQqmguEj9S?uyM2qaH9)83!(yM+H$7o_X7Aa7$KReKwfu^4L2Y_}jc3AZ4p(GdKkc z6niU#AjlyzDsZw^&D@7aFL@PR3S(MDXyhG7FN!DXVr7SBjAR=gy;&eIzh|;WFDt@b z{}fiTjW)?0U$xv!{;~siq3{z1dLmO6et28Vj_1=Z5sEv)I}nM<;x7hK7W$ON&QK2O zCNf!XrO}oMY7H$k61}_7cJ<=#25kIr><+)3?UD!UI4rb&Y~)eufce36f*%GA*(Ja} zH{n~5YKfchjZC?;QBp3Qj28MDKQnB{T`~#hFC0mzDUcubmDa?NIg=Eb8$HEhIK7lx zEH}Ui3pfC*q`|Lbj;omSny+-6T{M+WI zlL*Uy#Qaom=J3Iv+oib7K{mvN#HEN#>MuCXNdd@Ro+`!{QgaD-m8ZgprrqDLsJ;5X z`g=#>5oUnGAM_^kHO_g{g&Z{0SLiN$&2ZG0;2!N{BlFMIGG&^=N{( z3^|C`F#&oDa7xy=4Dc<>jqnq$BvvTk)q;DekY$aR@?pBH$24)ltU-hr7tCs=7+WnV z#!d%argiPv_J|DFw}`DQCo3@A){vrnZ;rfo;U|$cndkmZs9FL{CGsBa$H!2%W%|d z7MkQekO+K(S_qlOE4VRQqwTj5C^V(ufZvd__PGmxFNSBy+*j8Mx1%$#x zc@b8a5={%?d&&54k}tJ~h|M(9t_6?lLkN5N0A9TigS=vUTq?LZnp3-4@B0foUCbaV z=#Qy2Wp=4P{TC+g5-R@^&!Wwo#OR?-+7UZ7H3X6l2J5aC5{L9Q*DuB1NJ(>L5gAHq zqiiD|EVfhFQ*aT=LNr^7*x6n3qIr2o=H*2!36V3(1pLXi6NsK${ESBgm zYH_b%quLxLG8E+H8x9C>ml;5;W*F5@Lvv=)fU5*M1Q~w23_oFr57NL@ehR>S<@+kV{d~Ko z|6D9!n_-Z!{X;9kdNr%qHw#PQ)w*R8j`Oea+6*mXcTU#IC*q2stbpE-3NNd@NX1Pc zq6E99Y@DYA)?#*QdME zkFTx)7xvDw#RKq`oVmcW{3)2^DMAc#5;CRqv(|@ zbA&it(Jl5^mj>tncCXEaT>=MGjBpBHJWSI=u05^J#gJ~_TG^dbU6_f*tY{($#i7`# zm8;BS&cokc&8tmu{>uC^pCI&Og^482VXc<$!P|mlUP(|NXB7Guot0p}Y3etkKGmrOU`wo@Pq2v>zRW-xOEs`mJa!l} zti9L`0wr$cJa5dbOec+uS?Z$8v5~Q@^54eqzen~fl*I)B+r~vkL;1aLqU)sx3e1~TgB^kFnsPC~7g%VU&P^}1O+VBSo*HBtTp(oC)3ggSA)lWy~JaT_uEOk5(!n zt)hhd50nt@lBt*lUMVxeLX1#CMwv2NENHy}!v-41Lg$Zq3q}h=7-FdzH0g)Vf%JCi z3@j;R)Mm->tkdBF?G4h(-6Woa{xed{FO0zPQT$=TULkmbivm8z? z&C)jlUMvADiPUnRc0*+|z7)VqJ1<1wp+ccDLf|sWfWG%$vN((j0GLbPy>Puph`@W< z2qH?|6~GB9sG(7&k_H<7=*GQt1lO^D;T!WP8zEJfVinLjy`aj7Xl|ykQ23fgFD{e? zRYX2E$_tSHzg<4m<9Y*J46uqzs9l!Oudsw_$l+*&B3l)`Bz$b9CzebKD-FOUW!Bd6 zfKbRuWSC0$5F0tbVzQnvBSd|i;)i`;yo|{c;lY&J97%R~Nm$kg1dy{_q-36m?q%=KILCJIN2NV+u2w_?duPi(rOqMjA8x` zrpWWz1+wz>bY%?`+7Q$3iB7{zq$f7>{yY)D0R6ml21}V(3JLh0FbQFb!C58rN0deA zFl*s=YK}~4IJg9)h^&ktKB}eQ)A$!!tN4Fu3V_`gJJ7S;EB|EMAbwA}R6y5#0pD~E zB}90=IvoiorPVqFHWeIrf2Sk=#mA6eLKbt5*4K;Ht%S2Xr@Ij1vXsFNsB`J3GpuDg zpbc0lhEh(MPU{HPrECYdkBYlnH`#=_^WKU@zM6%(UgJQ3>_60{=2jPoOvz*bUm1g+L8Ue^H%bij&YBlXmoK@Pig>0iA5b zgOH`Sf%%8cc!E9L%sQ``xS?(#?ruKo3xk5U*<2Mf=!s%(AZkJb3w8*2%Nd`JP#o_H znby8gK`ThS_^<}aIo262jF&JZkqfUCE}Q`uE)%_Nb>xRI&B7LT(gjf9V$G3=vCY#D zhznVH=Zw&Q9KU4)3x+uxJ{p+N@M~Uuj|-@+#-h;(H{)Ra*uXP&30NHNmZbstLhN@Z z@yWPL8JY|*d{tP?pK^f?*epz6V(^EOK=UUo{!rkFT!v3k8o^fKZnwo`=GLRhOfH*7 zJ(|oA+Q#DHZCNFN!Ml)5s07Y)WoD&~)!YyR8lm6dC$O6Vdh>x$s5Na+<^g0Q#26O0 zbcJI0X_Ay8!Ham)k^5#DO43wMae`Pn$)-brV(i6nW0o~VAUwo6hJRrW0n9X^Nk|#m zz}20ZzVyUP7?AVA?3uW+2^V}KL>EZyA@&Z~UhtjlIiA`cPtz&hBh71*8B8cQ*TOP_ zZ%g9F0gAWc0;H6Sr@lo54Q9vLiV$y!1S6aFrU>nBKNHN#yRC>m_@%B~=Vo*Pez#cS zrLQnyWM~}zIgpHDY0?D;#Oxw4iWL(2Ya7SY432$>d+woOB2pyLL|v7kb`O%ocGe|I z>Ire7N(Lfhy~A`*u`TI~^IQo&uihibt#vLz#$r*BoHVmKa>4~AV)I@dIld%LBOkFx z7DSU9<1YE{-1_l$rf^aT_DI>ES4|u2*V2_m4SsWG} zU;u0`(A&XpobAiG0}5pf?j|7)fKw!5SOco*6sDS7m_&Wf9!<5>3;1V_$%4G7-G)HwKXvnnV z>CeQUbeB_xEP#BNw99ovlXW(jl^w9<)$t5=mDx?3Z9=wQJE^2xnhE2hJg1{_0T3Ek z_9$445aMPV<2gfu=q&xaERYls6kHfoZ^-EaL4mg<@U`G%?&<|+)VwEiG z4EAG?6u6fs>a>fbXtf|JVD3*kiqc-ptqU6Q8Jt+yM|WYhD4u0KEJX=3z1d8cc86T1 zTk5s|S)2)J@})LKMVMo=@}C(`m<-fHRQ4n#>;$0P(jpO4Ns~fdKt_D-7LUu4<8_C< zH+eM5O5`i8&KwX`TUZPEIpO4PBY|dFwArI1x~UvygUKm+huhFVGc94zdm$3rIB|nT zXw^`Z4I=;pPyN}XbAYht7%(xWJD?`fgD5{}sF&j}Z-*I_k(E}|p|E=)mygZ_e${0pH9f(sW+3$C_{;L5=j zvq~HD)+5Fn&|eA1X->dm0}JUKPhE>D*kU4^K0REfbx*^D{`<&UT(yl|gr*VD7BNRZ?nOT4aF=Ws?~Gh)Ifu$##W zo8Wf{J_(I8`YiVAi128k;A<1XcPRxQ9Ll1Luda_m_K9eX`_aQ-a{99?kg>fmd|=nZ zI!{Y=FjpE3b~p*hapoTUAge;)PwFMA)ZV#*?GUnoMVr;29O$dBL~M1=8BKl*+v#%9 zCWMOA;n@c}St(aK8;}b+D;jP;liPv#q1QIL6M!kongEWDIyVePha$=`=fRr z#MeOEx9bpR#J{lqZ|7gg)E8INI+1J3PB z{Q_IUzN#7~Xud?WXkSE$MGs|!8@7*npBeV>%!~o(193dl2LK<&75)zMZ$f_IfELYx zAf~#BMj^ok~gbiR6m}u-U7FxiB?hRBMU8vUdrCprwn(Cu))hA_V zPd!k9{uwspd`vY3`M0paN*APl$}!E;l~*IL{ZbcV#1au=L=&Y1Vw&wGn1dQoSC{a2 zGL)baFXDDt>fJKgT*Xmtw-{o(GQPjS`8I-3GNXyNMxmJ0W4p{k*jO{z(AjzEOk9-w zF#9b+2)PM7#MDx87#dxSBKVDk3|$pv+`DvF!P%deN|PE^F&F~t7qOQ0CIqv+Ug0V- zMm`I+pl1QV(uwJ=^st|uE_3>F$lRaXpq1vxQ;j{+WtdR}2S5?;YM0Sa$xS4PNb2B6 zy6Q-jNI195!4+MB-HH}u;FtF)i{%88DuQ&RUnIDbs)AI5IW+HRQVaRgQygR|R6v8= z)j;k>in*W##I9sDQDAqS==41x0-RGs@|H9Vq>S@s<5(&c3qU>5woQ>Ji&Q!I<3{Fj z>}6)yU7ZaPj+?PI9Jh=g1YyQsjO5+vDQ^R-L1A(THu<%ec8$;{7}L zlOgwrJ2LMa>_d}=9J^gxZFaZJ8mKLHSD>GNp$4vQjB+Y-q_}t{&=S@1n>=}i9G z7#q0`T|g^Oa$p7nAN!5n`=U9OB6MtWl?_p04(e{s$2zi$4Oia zJ5$f2OOkdkuwmD$8NXPl4A8UZon$rntcqwR;kln8jKxY!m!N(srTw`v=o(=cxzYE+4Joc)%X(AeXg@>GP%Cr4iQfO z9HkQJKn?XTk4{OWTN*t{)7Tub!1yWPpc$Kc&ek=i&yPWQrw8-;if!i`A(&u&?<)$VumM6uXffLeG{KHOTZpT6Es z6#@pr*J9`CcdxgrPIQ|GZ+9XitTn_q^i~K~QJ=wZ6V8-tXJs9*qNhi=EP}awK3me= zPNJ-px)j{31r6z==GfKNYJJ8Wdq12XEN~u@%eaNI$*F~rZ>21OOxZF(+C&6k>OCLT z5Wq>`m1~urT}fk5>X8*g15NOOgnKWA?OMnR;ob{q$Hrh*@vjASpx_+pFj!7QqxbRM z1D`S08S%gp?`w8#(bzRM!mbejUmi6P6{w%V@f&JifONZYtiUaR!h!Xo(uJQZ7aku&@~yx% zcZOchi5bK-l|(w$f|XjyN_<%xYEZ1|)3YKu(i= z+C(|=ak08&1t~Q70O+GqF$c-uIY_95@zhm}t~4AFoK|db+@kUWGLI2xm|!K^Ou!Ex zG+-|@&eKFewzUP;-cP5RZF?DUYm zw#4oOUX|67Zk%uT9^$Xg5*ITv*ua0n*#ouE%j{80yZ+sLyMO|KvbcqNkbA>^hKK5q&Eo+-@T3}y>KkWnliRP zp_9~}E-SY!w2!x}X?oludn~Rhp0>z-F8Woe{=s7Vmgufh{ncXoV(Wc<-mUg=)|V?E zztuj#vR=`7!3o@HI8H{Whw z)ilAfGJPVBeReulhmZoYt77ax}#JRFv9|*Gybmh)+yC6vqc3())mj7-u8ynl>Gvy@yy63J?mw znlr-cBA>cUOg+q+ls#_wXzDFJ>rVTaL0IHalqI!K96+Y?QG=^Jifu)URRN|7y%gtG zVc$m>SE^NaU1ryv94umf9W*gb_$7%IDvgv%7H*p$2r=SC-jFS%1;#<@P{psy=qPt;(jBfdR`H)6yzNIR)>n zxAbkx?eUdu`M?5p5$F%|!#zwYb)U9Y*p>Bjb0&m|kFW(#-5U3%D2C@xU)Be%zzNyh z(oyFv+<@lfN5 zFo`nr@6}E1b~o!vJ-*#eAN*DxP-+>si@Q_>H+GcM>c6p^o9=}_g|=(&9SM=(MpIYm zL&2S@|Bgp%rOv)m!Alo)i6U3Co4OIyy` z$7fbE-2g~yj2!yLIvZgXV?@G(qt5eh;RI&LY7UYSnspPu!0jUZdCo>%c#qxJG~UvM z{i4`fte-?`u|D@6dysXto_~+sGkV=d{qQ|@%|EJNrR{s|yyO(xl&{v!_u4%N&L9be zEc^zHHY8(N=jX2{HMg-`On14*?w&%nh1pQJVdt9-VgXSvyx0DH^rh+AzRw;3NKd)X zcC1Z${(W}uQgH5w;TA#!sW0?j?z4}zT6OLHb`Aavzu&Ig7b_E|P0f%IeMq^-8Nf1! z<+DDDfVn2KVhiyH+5)Zt*R$@oyVoJ%os<|pG&&NWM)DIAe#LQVGmh}d^45R3->w}3 z>4~X0C7l3P!7Sh?0wMUF8U`{e^d`y8sr@Hh4+d+#UksCO*V+y7)&?UxPerMwt|QyVl#N2vc~ zz--eaR@(bof7ZWPY1bBBhiiVpMWM*(xht_6zm4mMS7Kd#reDXSwM2i7Qse#1>n?i$ z+XOkzF7vpK<+Ob{t2!aUxkUlkfx5YXk9p%IX z$ynT$4biO2)7P)EkBwfN&|6m7y#~1Y$<%7pfZH+B14mu4f9v6$izxa$X%$eywOZQR zV)xE~88GCO7TaPbUIAf%@1*mo!a*-6My{1Y;2ERm=?am4`9_{3TdbbxJiwMD+?HKL zr4lcjpWYG0 zBqSwW9)uElZq>Ix3YFtU{rsbL_nvZ&G44zU&ri+mR?Y3nh&DwEIb zmY8#{Dq0lcM%Th?cU9%lCR>0(f|{{8f$q&i_{HEY5tAYjm5LEdmHOHpJuF8HuQ%oGrpLtFN2?NWE=b+%fNnH;`u*I^$)xlAyE#!g4q^T=$`SRN! ze8bvsh8O_F5scSk%xj(mo&fl;Y{#)(6vRq1>(=FytPG+PWl=;DE`*FAb2AA(!95#V zqgY`%5-z!_SwoDih5if4gCgfh5z30f5IZO7;T_kF-yJ0nc3hlR{~hbW;^ddgbY9V> z1>diPH3q>HY6UDTs{mUK3zyCt6(6$SD8xNPh#Q6ERRFE|1qzGOpb8+A#Ab1$CBy~= z7Q03gTOR0WVqK(YPu$8QRc$0yVH@IdXdw%zi-!FIb2aIFuwUr=L!&+2IqI32XnfWA zp4N~D?kuP`Q$&KZheqqr8MFyxU8Lj@{+S2;K?p?bIzpM)G!8-uPzY@NVB4l(A^wOw zfK?Vh@CCe^Dn&jf{UlE5I0KmQ=n{X{W0)v2<;Tl+PefoyM(J>2#>qLNuaI)bqWY}n8dmK*43U0$>(WBmb?)DGvTmCzgSv(tLdC$;$* zZ2!ohXbJ&0vZzZ&V9S<`VuBmRI4CP23Ognl3!clMurmIsYo%b20Mk9`24BR2S z@qu7)?qVV8pMD`v7DKUNM4SIU=}1JI|C}J}1IZThcCZ9O6fC$UBvzLkb}=}mv)JP3 zHzpM@!Iw+?$PIAoFD1VXcP(YI+lF{D zjl-;h#pIX%m)qS-vo*QRW|m1*1CksWRU^+=H9G4O;32*NV;@Q8iq-1_m<(30|4vq~ z{}i-`73{wqj3rVZonV%5q9HoQEMXXlz$v(d6Iilb!cQfPDA+z{3+xoA!_3+ELzj@O zV5~#W&LeA$$|=@Q!syD>;M0&esc4{Gh!&slwF}YAE6_>>H_m}}ksoLmNg9lxU1YG> zkvYd`7tnsm5M1p7WN)O5FbjMef^Q^Khz9Bd;z+^kappA*%0~dDU?mgqm74-E<18k^ z%3S3%RLKyFQW@|7w81sbcho7k9X2{e!blfD|TRa8o12-$Tj~R z>*aS|FXIK!7`Buxc?{~s6lEqEU&JO~DJ z6&_>~gggxt9t7=?8eG_o!V?X-C@{o8*Y!#j=~*w?MHTbEL9PVkpEpWWc|~r1W)B=ZYE;6udWcZ}_Du7+)qjn^s~AiJU^9p6M3IgDV@Qr{I3z z8TjqM&mo(R6s39`W({I{Z#p608hCm4AK8Z*XS zjAFaUv)@=a6d6-7$y)|D%*~f{uhdQ7^BfPdzCy?dX{37<{q$MRwwh3xa6i-YLONQxd{5T{ITC=tNZ(z6EIr2^q1A#NFIbVoNW0&93NI zAyxo@HP1@t$yb_PI9Nz{(+n7;KDJy{6eG=wG)gT~-V_D~0X~=O0k7M&Wxlr-I_+KQ1q`_&wSmksqu-D4h_?bn9lT@ui3S|eLGzM42sDv2@6|)`?_tHM&YTTAs7Lj z+#I0crZ?=Gu6}c{A`=LW|o+6NSlsmdMh}Jl419AP{DXKgJYeKqkSj_g6Li!3Y zxWXlAnKt7rNMp-}T;c#;d<6+}fR-?c8F~<2V~;a6u#(8C>56P)6)4e3Ea~XU2)e6 zSUA?6z62I(>`GAzDJtgm>>ZrWekfuRvv z<9hK_Nh9FEQRyq{Q=ic)IdGKrXs|F4%ZB1=-?kf*Ky@N@qdxj=yLLFPJt0-G9{Q$` zH};={af%m37g?(kv_b;Hvab z`z6ZtBkv&QZ~Hs&NPeL!-n9?o^!OqyP7~94@7h(h*>A%qMX-9|)LZnf-M{ZbZ)PF6 zjim#-6VPL^YtH1YH@E0*@7m{grMHe^m*PB;nxoI#Xg9#YH+Lfdxlup7(XO=?>Gd1! zQP$gH(SB!m3rTx9zux%1-3!Cn^S=Fa4Cky(oec-O z!GAOy+3z;K@31eJ7--n_}~6TK1Sy0x-G_ug!mlsd@^EHw>xLPo(LAO$W6@VlMQAah zC#wkk=6R*vHV`4@Ouk)j-)vV{H|xX)_A%BB{lgF7g1kas`GH;A-JdGPcDaj+GXdHA zz+Z-pRh)qS_x1B+1(`EMt{WVdXc{_$4( z5O`ddYz2u<*3WLW_ZznBYh?e8G0@in=S4nmY!#gcXTTRNUtHJsZrCkwh;@7qI$aaa zv_;q7rKbW-t!~xjy|fyIfa)ija&}{nJmeu0y||9uN9)LaPT!6lhTD?D7;(^R0Z=(Pvfw5%`&un1|V}!b=9r9X$ScFqx#StcD)_C z@(H2NP0Yv=wV2zK8yZ9p=xcV^jaUc|@35Pa=0+#|=?=TPr+<5shYomJnS*^Kju~q8 zxvlyI{Zh??<_`EoC81Z@TuxMkP?fVjxBHf2g9X?x0qpEImU>&y{~RG>oAo1~+l#=S zPv2>u2;@Ap)9xO9^>zKmPP^G!s1sk<=T-m>(1(kW>Lfw&O=ESdp8AE5@RBdkNUMH^ zf53#ku_SF%Fj|QE zp815-hT5Z@uTgprJ^_V2zqV_Wu9}1QJ^J0l#7SLY=<-=LrDcbnCx2~vZuu4heD&9M zW2xIS)J8WgryleMw4At`kJBuq=5J(G5BwG)bjNZ%X}4Xi@vfjSgu<+k%fEqcy4$m zejXV+VC2hFFOKmFE)*ejB&-Q@jY}S|V z0de1@7wob3hh7C`tx9j-W1kjXyI3Fhy?s;#IX(QI*o>0lgPe=8KJNQo*2in#+fDsg zfJK_PCwF%tNhX3Q!HV^n|MmUVzSd{gpR5|J$=6@5>Z8KMn=0ilMo01!&|JzsKz~$_ z%CR84SKduYLdNlgb35kSQhk!<6tU5#CR(bv0C%l0gnZrxow0CJ^$i>JN=vnPQ`apn z8#N5SQum0e8Z6_rkDCFf^hr_GST9M5%$^Dy=Lo>VeR|R)=M=4M8j~pI>G?5L)h|xA zbPR@RBG-7wr=M-X10AE;5>>THb4ps5#8h?kk)^s{OtoN@|1hS=@Gp+3G~eDBQ_Xn0 zCZ>9Op?F*Io1u8caYfZ~a9mX?^<4>-Kjb1&BjREm$buW2NwQnqM2L%PhQ(kl!02c^+?~+xB~(=w&QnR% zHSrmvB2ClbE~8IBVBkQ1)!jS6jC=8>-iYrWdN}bKt?uIk{sw~v{MHNNJxL#}Ni~=h zjiFWOKPOes9#EZ)BoR(28$pDkGaBU!y(g)L^>Oo@xB*MS5QXs@^+7*msh;|xJk`x* z0o@zDS!gBjo~NRjFJ%Eq7D^HpyyDhM50EIcqq(PTbH zzn!mCx!{S-C!MM8g^YSo0qiHn*5ML-O9AG2(F1xyftoNl3$--6NbGKKv#hIa@{3D^ zz;fE>a=Qyu4|jT)Pc33ad{YRSnI2piOwUn;pk&iL7hTZEib7R+UEt6^UWMEiR_W12s;VnOA;naU7Gh+@w6f$w)u!J)#&R_z1isZP zid1(>=6qGBKPkfcYSq1pm0boApHEAng@0i9=R!HUSPibg9q0(`8HA&7##~SUlW#I#yo;(16t=g!s2Xo`_;nZMZw?1_Rdt0Ql)9#j0{!j=h@9|d zxUH)?*t$=@-c?-TpK}a3}7n6G)WW_R=TJ_u+HeZG9lN4%P`Jm`kXQ~5aan{nK~@ccRndoy`rBk z(#7SffjS25eERTmHK56t^q~XOMq4l|#~2Z*0pC4WtPJ{ra#h@!R)m4$ob+=2Zn^5y z8@Y>f)gd?TnAhED98S#EfaLAC3e}gQog@O$;p!AcXc(uQK%y>9B|2Zlm3n)HNbOdZG5xzrplFW1sS-4JXPK@anCPWntyIl486+4w#vmxz!*r?&Tz;}1 zRHdrwO(aC!|GtwyuSy*X&3RRo+6P<6kE=jJn{{Eenph&u%S0v7IQ&9vd||b!05E^5 zRs(+y!WN3gZV6Foq98oYYqMjB)`4yuN2$G+8VXbSkaQfyxdRX zC?j0d&OQ5*_YsULYI2SE4RI-s>!!}{2PC=P5)9S&DPvw}Ow9N&Y0Y`7o9Y4Vec4Ub za%xbd2_QxQqGv)31ImbTD9fX|tMoyhb;WcY+SIdK-@M`hmJ2C*0Hn8cS4T4X_p|P5 zbhm35roueFe#{vnX|Nqxr4Q|)#?%AL?g#9{Fsp?)#T|wFkZv+#j|NFZVdcKNhjMVj z=JOtE0PHfgJylQZT0OF-N?SMSANN#aqqnTri+ZZxSWoEQz0^TbFukAlQlmot<9vA9 zrrfUEd#U|Fb076m{jDc;S#Q;^>-)ZsISyk=KAzOSu2tvPf9W+2CQ-yQH<8q8zfBH|H*R-Z@Te^WOoaOY3o)JO8~>PPe>r49f$UZ%j)TlJet?OP2+!JQKr zM`S+Q3RUeU7jj3DwGT0hBXm@H_r7L&6iG2?fz&f-1@$|>b;CRGYZ(M=~@0T+dz7twkUZGiot_#?8oLy1KwA3?Y z-OVv1lwH8G3v$bX3xvvI(G)n}E!HIss!xUAo)whQ;~Lby%Ky@#HX;aR$1xX~5P}9m z#q_fcs^K`lfl$)`6?_-ge&}UB*8o$JfvzF&^o?c>G*nxUYgA1^kKr#<8r6?L&wp!F z$By*lAiRd#X!vRava%XZ1|tSoP!^H%V4nWP0Fc3EJ$C@KG=BtzK~eqO0LDM zzP(vBoZ@#MY8p6@Ani`cU>!%gE_b9IY8OzF4;-la^!0n_Fr#HKJ*Ka8uRp^x822xn*mvxr-QoCUFosYmqiK@gpO!461>+3x5r83g_8e!T?61E@pz&~FY> z!-6lNhIHLv)ew9M*ExMKWaDQ2`@!L1AT_2>AuI4DdglZBFN2|+`A{Z;5*SW`3+sKD z&Gre?S-6#h_rcEgaXoRLFzn$1^Y&5o1D^DFGBrq95^cOasV(6z>j188`>1oFi~nd} zRcrfTg+>Oju-=(P3c_UGzN%-#KPc54Y2|4g2zacn5A=Kcs;U$G;vL2s5?MZ=?F6(v z05mGig+>T?MA~iEM-NfGdikw)Qe>090!0F3cPLWe-29+^YKTgY+j}#DzO{sEtq&Dk z8nE@}$`;+YpK1#DSO=*CmsMikQ)EC>Ph8=*EFeWCQ+7|W*NL&Y1BQB~2Eb+Le5>1Ks z9&05|twI9hk%CD7?f`I`dHT)+R8#-Qj6*8M{FrfOk3p;&-PYBZJI}U{j5d1D0jes+ z%r=O9h1m&Wo+GInp&FxiPt(VYP<@)DM={-iX~cPYdkXx{jEice|9LuO0s+K9W*pyM zFapZuJpI@RfHGBoIzsg-&8lBSMZM=p0rc>ZQg-4sS4Iwt0yfz2xh5TP1A2kRz&V5htb1_-#y5DE?;FvkckV42h_U0HK3 zJf)I*zR20SSie3BQ#4P1JxZO3KR-B7rE77D(Kk^Ey4Rp(XAK$>bnDp%3b0Qes79fR zHChdT&e%K}Jou0L(9x^&0(@cd(jVPGH+5W{zM^H1@0rhUy_d9AZs{Y-PDN2r&KYho_tR6pB z4H_K`5ITc&zLcFW^*Se+diFl~ynvq{I7_Tlv zN4*Y#rF)J(_7L@BY%K3SL{-7SyXFwp4;ztfhlqu$a033oLpnj#@g$|YpWq(%gWL6q z6R@AZO8*)kt%vmd397omSCyF|DdF79<8e68fc+1YdANdiT9ApjxMaP4XM*|#KsoAA zb*N1<0nLo{h#SHRnjddmkpVX8D>02LQdyA zUj~wjBW{Q!Z>6yN^L;)hatuXN)AX1l)Y*`?%Z^YD`RFx{*4OC`M}Ss8z)d2mJo@H3 zU3Db3P@9N&p2TpQv1Au~4Hv*rhw@@@K@I^zf%79?bczigJo#kcM1|QOTCeEQV2L-=Kje z){I15NVo=;jp0blByTt%C&3?yw2F+4ASR0(G^N{4R>MJ)&z`LMTZ{E)Cu5-g)77V_ z%kfnHBXwbaT1yydYC=rW54Obe3SkexnmB%#aANt7RNo`tU>>YqUr zgE4J^^)c6NsE8zl@}Gg7@ctEa)mgJ)JD6B|JnM#EJ_yez)#_J%tV+Q#Hvd@d3xTJd zmg;ide445`&O1tq)xl72MkC=L$c-qk>_F5~J_yduY3jP;c20{9v{6g^VTbtz< z0${etFA|{%+%-|?lst8ju0;|3o72_tAg-5ASM%#Dq2-{5J-l{1CJ7=^durf?#*q}9 zf{Bpk?Fg>!mS_dN1}cq^ZvnZE1&oY z7-(h<)?#X2x1zf(lN4qQ4#Cv9XLQk@#dTyk&q@MQ3puyP145*~y8z41Bo371F3@h7 zKpeRq4xHp94*{4ZlJoAsLnnb9IT0{maK~tKBwteOGmHgOiCRB7U($x~+!&VZNM^I^ zaY#wT!3u7O)r^fCCncLBDb|Y|0<#FNX$IAgIUDDOx|oqIb%)>%e}&v_E?1oM^zxzl z?vL~OmLh?j;WjkxMsV0n|LuPu@E+EQpQ&-MHXZges1q;f=|6)Rd7XafXPB0qI(3Gc z4psApGt{o=*Jb*;Ghq!}qr04?rYF~J1l~63d1t9HrC)dfc5FLJQ`RSEp+0Jkov4nj zdd~|i$5-YB;JQwIq;H?7>>f8ub|Rcs!yyi!+eB^vFN{jxG!dr1&AQ9kYFyus5V^rq z+^rz(^ZBzOddaZZS*XD1eO$Xm8K;Y;sUG^;v$2E!Sg$`DiqS%ye~vn!=A}Z{oy5IX z(!sef7lxD0QRz|_2ImF;_0{LVJ9D$X_Z&48gZStiFu*VM`R9TGEztU0bqt`|a;`e4 z;^VS(1cTxZ32O~tM^an$==0Q|AwWq8-Q;7E9my*C4mVz#y{CIz08HJi z5554KfcNxy=4tK)>WnIAMKO098J9DN2KN;g$^Z|zP+f_7PhY6)pd^?7dLI?vnv&`w zRUH(e-aA{=Y)<4+7fE9mU8EYi&Yd~48fai3S<-2nsh3@(&MW=WJBtrob-{IvH|qhv zR2L2e_K>ia-7Q61nA}KeLEPk-jN7>61GcQVD5^LsnwqE2y#zYn&HCeCs@eb&Djcu+ zkk}UsB;zjz9&XmZxEPduv%c?QwR{Bn%A+;3l*cb3h?ibSM+c|@8B{3j%VDbAQ*kezzXY4RpwIEY3D=5$(^OXvPh zRUeNcR0RrD0?G+v{Sn`EHePU>fRG{dK!1`-1U*dWr|H;1gnB?dsOETQhPcjju;+JR z*qe0k-@|3QNgwrlD9#J@ir+)~TBncygE|fD>;6Be{j8lUKmG%>X<#GT3LSfs9@?r- zvc6h*O)Ko{Od|H;<^8L4$*uM%J$Et|&ind_$uJn~D$^fKRs*Vcc_9MiX0E3*mU>Os zUxv1)=~FLLUy&L9_Y{=@Gkjx;Iv+$f;c|5wxahXau~}KCi>IpQ%5~RN7eRW+>Z2;a z5Xr6jsHtjDqcG2JLXH~9J;;N2YGWur4afeBUOE-MKBM26ik14Y{`oYu!u%PeCrnpe zFvkC$9xx)F1PK_?is@=XPqHWs#DUqyM3aU~lwF|?1EcxT73$UQPe37Wj+`&{D?o#N z>{WOA~ zW(r22-&~9FJgnzj3yJ=){`gv$n|A0S*QtK^bMkenG1TAXy6rmbSeNKKuLFHtuAje7 z4MUySY&8bR9XDGIOS)sfbT%x)fNQ~QtmUiq+S#fmC4=H|-YJQ(*6*RG@0tx=WSSmu zJ=W9|J>hya#6<^`RSz9Au2;w8OU+^ochmK1%%Q>fFE1yGV6Q=WWYEIDh&#i-laV(V z2CnHoBD$bqFO8v>&k(pdcaG{_5`2k+tY*(aq{bEc?{m~qeKzm~tN0g*QMKxLhA~gQ|<}Dbg3+phmFh4Jz$ncHIpIvtQky29v4~TaZOn zMFCaulS@^{+^CMK7c>?blws$LOCCtIv|Yt$ZyN3Fc#+gfj5&y$f~G*9*Ss3GZ7!=3X~OU`8ceV+R7 zqM)ZM^r1K5MF7||edkR|^(Xo<*3?zyfuRe^I3s7U^NBfID19*-pWg(9_zGP$AIpBK zK4?A!>SR4@zUp5jm?<+<`S^U*HwTW-=c^O4;P~OqIdH7HS*iU92NGlu4&OWybEb3k zrmoC-H#d(fx+`pkQ+1aG5HN4(%mOvx$ZU28Rsk98F*L9^P&(N^*k8(JasPnn&CnGK z1>InJef60O)iW6Fz+1ooC+jnBf#N$^&%XtV&(xJ0Zh_Mjk0Tc2akBo+VznJY_3T^K z5muXCbt|wnQ*XXieO1v`P7%YbKQ;v#^pw;rz5O=zHNSxEXMJhY-z`xeS#2w~ELERd z7~%Rmuoynq#dkuRcu?>PHH;@VPl4a@wXel2rL%`$CWnhF)>8{H$TQBK- zmaF}{y!;h5s1OAXY`>|y^{ABloAc2J5YaZzx6tMsb`n91VC^iHWiWF%<${;l$z4rtN5_*IHi9(1pX-XH6-rvve z-X)hH;P1^JdG2|3cXoDmc6N4lc6OQV57SEOx!l&Y)EaqZahP%ZZ!8F-EI)?%yh6E6 zeaf)O7x4kt`W1M=V+uZ8;7w7&xV4HrSJ=KWE!40VYS;_u_Z7C7Bz3qp)$9|cR%Oa` z;cW~(3y9n}{TCjUEu+JHO4(D5Xk!OHT84%BL=+bITW0q)Zl1$KSjZ`R9b+**%Ir?? zO@?YoS!4P66t~hwdCQ2j{wr-Zlj#6rBHG57GcQoZ)u7w~9FMYXj-PfxLN9C{<})J| z6f10^i!nr!AP8s4_O6E`)2cPLede1NXwX_)f2=GXuZ1P>6jfhm>ubK_m9}UdT%O9V zmQZoKu7hZp4U0iVppy#-pl2He5O1d|5Z`RD#nbk5+y1h}k&-%SQKYawxIpXItK!Wz zIEqUQ=-LK!@l*=mXq#Y~LCZJVLT$Ib>{>juHyLsQ(MC>rN}Hf$NwWoo&TX_s1uVM+ ztnD3B1+#HbhV3u&tU$^=7!hnSK~tHHYct#c!DP{2!+iA@nP$)Drt(quO|}o3&O+c@ zgyEOlDVRcKA+7jHWk(x3>MuV+pK~6 zr58S0q7NO!xsfH z^WJXTXy^ntciS4dE)Mh!rcd_SD#~9$@>hZvnDFsqk3N>gl)4A{ArcS)Js3S-!m`T? zS1($F^l!Sd2X2vzaWdC74iA^T5GI4E>|WbS3CxGa?X}tH!CqS#`RXlSLnvh*E`e>d z4>=dpTl+AHEv6a!K&!=+r9WQWXZrv%$IJU|ZK4(j;s#t5e+b+5R-c}>5-y2mwIq^9 zoPOR9nS^uq`xP+198B){R3QgSXgE*5Qz zX;>}_ET(n2*z}u;HK(sMy_EbFD?ohh@|&%d`LTc6{NHRJDf;1Uhkc=y=8)3rP~GDJLX-BX!`}=y=zgL<)SUv3<9M1u~2Gw+2-Mf1(nT{ zqN4Hs)@8NMO1f+d<@oFyCHFgWV6;H^am%zIxt(#;gxNl+nfB@!>(9dJz-8dEj_zKz z*-EX%EvdLy)C?_Kx&BmLq3&iRVOGDgNA&Y(V%wiv*m}-4t8$R+eQfJd7fCBOxt`$YTr>y3J zPV@h#Xxaxdt>Hg5Ud0LP_cSs^F)!ha`TMfi4=9G})&V3Q`TrE9$9po1>vfeS_PWZ_ z>N*C|I-K*eML84cUFX)~#A8t+y({6Y(s1%LoIAw;yyFZ&O0FVQen$d$;f6xw-5Uy# z;Wvun`ahXvjn0y`hxaG@#whqQ&2mY5i`h8fM&7HDn?Savm?1vxm&- zeM{x6cuVE%a7*Rvg@-dcb(cA(=$t~~_taofB z-z=m=hHPtB0LpZ<)p_74I?2=mIyqB9(MhHjplGKArQ9jnKV4-XWZY3bdE$=E7Nf_H z0^j9dz?1c^>gR@dIQL~238&{>1!v4%#StrX&V9vlzAkg#Lr&-7ugZ_{_f+u?_lmNK zN=v?HlPtU7UeRh_k>w8PvZW}85ZX`_!e|Z zvjyJXCRQ2HnweOFDTn%+*jsozWMW2GZir*i+(=Hm|9Hbn-B8i1ika2J{>aB>_60JZ zF*E7B^Vo$&`DLgvD)*2fjHr?etAY$YTnaMKOc&;hPfK*l@q&~%e2jBd*}J&1*YUQ_ zmDMbDLMaxho>*WwDGhazT*pn}-P4U#D)ooTl~XKN2yJm=QvLW#XD#i{8ing|5y?!@ z@Uc9p2NE^HLPb)!w>t}l>&Q@dRvU#jyR!=R-1VJvH?-$=^#H-vQB@CC&YrD_bG8Qd zY@d0s3dlCogO!f54@224^<=l`Ktpm&xqw)|d9doHT=Mi}HBg|TCo63RQm=S2+1W!q zndG%)_OH7gvZEUb@JaUhGwT&B0f@6zj`eRdW#nv4n3edEmi8OsIO{ z6z|O}DA2&0)sVvk<0IMR+?Ja5wv6^>73>*?6veTi8lgR zQ#|J2A-`VKUn^VG*DvspUpHCMwh{D~g}slw?Mt#Uczj-xNiB{_vPyXDD#`u_-ij~9 z>N(RJjvLUiVGWZy{6$JG#p)yTrc!FSO6&+b3v#%61p=C#d@Tdjr_KeRVtkb~TF*%c0P-k4n0<~Cvx8Zg zQktS`+?W?6H@5iESHI&s@Om7~B9SXHguRVNatM=dWxzj_Hiod0__Q~KHLn19X5S!& zCxLzJg938w7qFB~zC-nHR9cC{k4v*^reAS_i?s!mE2UYP(i)2cE(o;@`vk<>I) zjik<@Y7CDGMH_Nycc_v=S3>ou@Csw??4#&`*?E{nXk6&iFh!49VJz03?@p0?2*;u1 z)ft^HFkI2Cez*qTIb4>925WFQ`P zG}aW!?r*OpGg^VY63t?3>h>)tk`K3(No)%E2cDE}>X?rf7jj6qjZyvcMGT9Rqjgpc z3%5@g{hb>QS4Y*ZgE8zKw5y&~jgcN!40XlJ;k3o7Mo*pg^t2pWhnEdVmpvQ-{F%2GdPQh5$a%%qn%>)@5`g;_{i=_qG& zxoFzWnU86IS{`SirjkQf;gX=Ta4}Nzq}iB3j|CHT_x?OiJ1^U>cd4VSe*5HAjWP(K za+50vh*Xfr41+CoE5mq$1+sh@_yF3|YD4D2&S0`QK&VKnzQsY*2BHA5NrD($3`8w} zfO1s`0?S=Q7Ap>-mIe`379dV<0v6UnENTJ-Vt^HbK(ru404olnrUo&fEQ@L|SAu9* z2%-i+V4JuQgjIqN#X;22APxbG<|8DC$U+d+0V38JM63i6UmQer1p=0Qlj@!7bh0c9 zYyL+DfR!%-^I|HjMfmJUKtXffE)ikg)2`sh{SXBU%ksJ$p3EhTh=EZ?kEefov z1~y#+3ois#1;7$NbOM$rfi)=(tV&T}RTMDu{f*Q=mW2ujyR?vH+Y~QbS(PQ+JkHI( zY@}n(B|69wor;&Jq)UXwp~S+C)G*Gej#p)guEk4K)Ft}K5<@rAOy?5aWr_b4FOi^2 z9FZlCZJ1P^g;sYo<9%7+qv8ePRe^$@hN@*YCS0U8O{O&kzc%MSw`BRfvMPhC!X%d;r+lnrzV5DQ5Am4w*8I7E3H9!6qp1>o@8dTLvNg_U*S zkPL4Q8RfNjnX0CK$-FB)F8o$G7D6hB~O&G=`!CWu;`L|&*M7jFeL|K zWM8JyB79Cdkp_fH6(S_B(Oyvmp%n`FnkRrq0mwhHv`qnpf!S;vy8(u&sNN&x`-yRQ zk5TVXm&``8WGF~eOchXz%*Jm?`|$zv#fLEY;r>WqSzo<}%J*@j@vZ^l5@2Bc%Me9B z42{Iy#hOttXuB4EFMq)O0E~U>av3JcFJ;y4s(2kB#lc`{Ae*%U#$`stq zZ0A3GQ!W?9*ivSlkVefavk#L17Kj}%+2Edu>*)2>q}SK!E_I9`O#J@_N9qFwH`Ljy zlv$UMxN~G8tNS`2xepM zd>n;JQ14KA0N@1ms=}(p-CqhvYLih?o%=H?$qU+z!OPV*f4SEV=LK|wr)3}QuEJ`V z_D!nFf)XC?MwlP$VmsQ1V*$zyq!{Azw7{KhWK?A#dhhx>lT!)jHeplKY!ruT{&%SO zY;2cA4pFTEzCVJA(FPA3%>b!Ad%`CUMNLq}3J`kPv3HC+8D&`vWCtq9Ygy^)^yY+^ zZ2wiWj5b)pCrByzs2rE5Av~kuYMDV5s$uoEncl0$Qs7Z=ry6whD{ge7FgshsmWSBAEJ5Y&s4t_t83o7hrX)C+C96(samXZkeynJRMIuk zWSm}1WoxsEz$2qJ)`TO;yAJDNnwIua9W3?WG_}WKt=-q_$6DBQvpbMfw_{k zAyxybIHSG|*{jcofqpI72#XVYp&uKuzRxe@e)JCHUtNv4bH$qzVVPJ!R}xtm7A0N= zi-wO!tN}9S)4K+1fw+vz4ff8nYmmfrU$6)gw_!mIbu@yJ^w$flzVG57@Du{zVnQ56 z6&tfrrm<-o8)G?Z`jPUQz|yyb0-CbU9!rrA7lqS_rmQZ$&2P%8nwHVwrYsR}5zWAQ z%cy=c^){dx6CTS|{tQR{)6K9ZUQYhaRgU(}Sxs-9jgka_I3V}})v_624HF!X27ZnGL4XE&icYZr`;M6~%@I}mLNt!~L`@RhO>89_<@ zt8Q5(iIB=5wu}=HUKTh{E+n5;tbNrbL0G6G=8r4ZeP(H!LOMdvtPX+?1Qzk0#sZXb zH>yi9g4@WMWgd-c#X6v#W35=}@HG7;USk?i?geCN_gTl0JNAU0(`lurd^;oNb;M89y))F}mc4Vy_ji~n`>-c=M zVP4ODk$qK&_4t=q8P9xJ?Qu3foibliRa!c+poqezoO5o<2{eTobyB2C=>#*z8rs|m z%j>n2-$@mYeVMg!AeHhmGNjYymsNI4XBGi>f%wiW%u|zNvY^zqswvc&Rn+~C>#9MJ z6T06ax)G}r{r*R11-#NL>@Dw2KMj!qa12P?sjsk3&uz7h;$LL}{~~sCv#9;6Y+NBV z%D={1x-1B?QOC|KhVnWvgu+V8c#Q>`;m?xOg(XN@e&7{9Zg+7pXhiF_MR?hq= zkT&#TBRW2Y{#D78VaBc`?hS_?hEPA41T#SgljVX+%tE3(W+4yjB?qaHwCbFWaYkk` z{w`rTgnV)$MUj7K!l$fTaF!}L+y!90q?4q{s0I&s_s`-3;Gq&Qw=OpM95QmEDEY;^d+K>J}lZSung zgGJSD8A#VY$1uJ?zF)A2=Rj)m1v5-}H1rFIiVIZsOV&C%4-JZQ$uzTI8I&G}AA{%H zN=b)C6E>|1uwDEmd)s^;*nahVY`=* zG;$zI#>00IYR#o8gCGF&D0vXN`e54BLF`*o=M#axSm;QvdU;>770r`|CF8oC>7`)^ zF>3RHqrA<^#V-^&lz~T&0C_DsKH;8PoHaEoYYiCm5PdR))d>V!xaoD;2|1->p@)NW zLs;3;ay%uJ$b{uN7=^aWg%WI3`E+Lpiw@Ow9gvs2$jb6nsu`&jzhfZ@I`xbrRciMp zqY6eS=0m`|B#qM;tMW4rll1wH*`o3TjU+kfE14e1Vrrq8tcJD)P?vwl8i6QRzC(}f zqHl*X5u)qJl$lFA@Uvu5`cM{K!3jH=rm(Y|ROEp}l`bG>Z4(NZhOwA9-BvqZcT~!6 zD!W2Pwou`M>@9~us-LE>hN!!Z=NOZ?;(-SQitzZbsuEGg35$oBKvW$g}s>o2vYLN)6B_gMG{H#i{z&LqgaT&r*BA7%2eGwS#%#IG1rEVR$cJ= zXf~$uu0ZCvyu<{lE?btYc(1Cx{vr1Ihub?pbPS6DjM`(MI3J<+$FR$2PUo?ZOTW@D zW3e3CPydXCT*@PB3dZUo>Yc(uP+-GcP(Gio%w-k)&il!Wf@EC&K?_Hc?UqL!O4;l+ zoA!@mlarR?YI>Y7e&5HKnWlcd=VO?W^}#yz_O5;#t8=}h-)88X|MM|^Ku}baej9gV z%~rqO!j(dZ1&VJye2l*rsBhhMsj0fun?A;tfypw*8$QPPB>l6Sk8yUmD%KSNOZ2ZU zKE|#^xK_aI`?>~j3z2Q{_L_bhsncFXU}m8Ey?%Se$JjJj!GX7nY{pI9jF)jymoD8& zf4{EZUP{uhBQ$O=>bE~N-ta?_peO0H4mxe7M!3CBTcqjI4rj470&R7!p}I^P{dP*j zYpu)tpwn8Zv?ODi2G~+3&eH%}_!##zhRrpIQMynw{dP_RY^uvl(P>R|+H4K4u})j2 z;k}^KX6QG=$Jn7eDG}}8BQI$%!y`fwY_J9fpO2HeMGbt66S}(kI>%U@qn?lPy#`m; z$C$0Z)zLYU^;>QIHcP+N(g;1)9a2-jO}6)c4Sg@wEDf+am{I?#ra|1*g{tbeQ97-P z260EHRrWC^BrCS6HID{WfZ%${AxvROgJ=<;HGN<)VBH zcfj0yPgN1A-=t0sm=T(OqsJ*I;j&3dIEt`U6%5mfgH&h&Ujzh@VDjYcc4ptwnigkQ zshlCY`nftSSd(;2ilSkVE;mCrDNw^)p=&6m)0XQdl~iv@SSP507ER#o7u8#U&N@0v zRqwCgrt4Pt`53qt%lK}aYLl-{8@~Y7FEgeB)oD{TGTu6E$rjaKFHOS*Hxy+&H5BvO z74#;t@VaA1s!X_OL;^o_QdNvQNhE)ax~kgkqTBsvu1bS;CmAdGS6WT1y^q%Er2d6N zE>~H(Q1~4n%>1@Mdzesl$`wYo?bK$nawX|InYD(5&YTRBP!3i65sR?HlzW{;VY=H(L8d!$zH?bjhn14HJb{hEuY@QqlVU`ESQ5}8H4%r9F=Z<4tb(e{(5jl8KOatGuf!Jvr>+7-a8-@h zN0^ME6v%5TV3IsY$mxHFYw|D{R@1!O8){6 zuG7E3f9d*{hmWyA|8n;+GW4&C;KQHwPw-%-{ssQqs(*p^w(DOeA7jRYakO(5JO}pC zrCBV&XLh0l`VKLNbHcJF2CC^q`0nLVPc${|5W|cg&3L2}kMf?OexcyY+Coo(- zZMg}jgDmR*6N@OPvqgffN}!L`j!fX@AwaKnj9@#z*Y}e{Q*BBAr9d>1AfoBrMXYy_9ujLzibm;n8eLe#Hkc0v z(wE4Fi?0CbJndf0Mu0Y*mat)X99_aXK}J+r3Zvs``d}&RhL5|JvR!zLT?RkVBXn{Z zI`=e{UarzUUyig()L;dx>me83xHOiGm5fp93aFYRC}#zv)FryJLdl1EE7_Z-?`i5v zwEhwuT*-u|G-A5Q1+HlogjGJ3T_uh4^V_dtCe+zsHG2=en!cK~^wi)pP4r-ye++$l zkXfkq8u+v1(MM}o53udNHLOC2ZumJ9qDLTjjBGeodWR@rEtZ*CRDLaMURGzB<{}T; zD0)AS7(f0rnG1Dsv+sN6;+$p>zPLE#jg+Nh9- z&tTIqAN-O5z5fuM&tNZ_E~eGrgxLW!9{n?$fu4-tjMqFGuo-(Rd31d<`^tPMkOo%t zj-u}~S+My|AkE5TgOOHd3#%M<-7fkP<=udAUc#v`WgEXmy|%zMag)Yvfg$1sE#88j z&!Zz-SR=Wlfs}=tkl9cA_+_gFT^3c|%A(_S+EGWEj(ZHDfC6xC(*?H6uoV^{(r+ua zgO1a@tr$LsD0eGtFnQE)CyS!EZIC&)snIq#Am&m3Z9wHV&D^HMz{zdMew%!^vqYq| z-LBrg!drwxj-N2e)?nr6qM5}4lhAL-P~VXu*(@`t>C8piz0A^*gr-X-F%Bxj1SXhl z7sv#h6j!YC8@1m7IeC%Z-J#ad6L+YUo5a=v4nvF$eTNXXx(||hr;<%bZ0T^U{*%V; zRQ9h$NDBbBV&72G!8nTQ=*CX)<6#Ql#jLW2>hHp~$8qYn3rq6-M7vmdCQBrgNO6;s z9xhTt_#(L>>0(TfAvzS!bb1#C@kI*Df*JQ9y_<#os3Wu{OAXT7S;}Y=_X|A2@~F=* zkfetw{TCK(?@jn$yJCTgt$F)Exm1{z;YgEVR7{qWWZjK9;18;?n+b_+m)%%o9;Xqz zSsZ|_-mNOUwHr-1P1W}(GWFfVc+>q3+n}Gj-Z)i}PzvdtDP=1(D%m1ABYQ0W{!-iuLpg{=EP;;Ym^KCaR0`&e|0rt~?plq5=osHh!aB|D$fK9(#G!db3U zNc^T@%Cl|JYLpXS-9xZcOgnfbzrRlR7r!l#>{2NoC znpLd@XyeE)u#}u_mVw@+v1)xT#?uwLm5VWRm2AI)cGuF{{>ogWSnl{6d&@4thMTkm zJNz4rdwJC50DFMPs|T_F@DGmXqS!uqc#!oA*R-lGW85J=SQ~VdwA{gf0~>iBi^JHG zTS*v+CGgb?W}V%6usa^2Yk43`Hboy|<$K%+G|Y%-WTb45kT( zA$|_h!NcJ8kRsyJqj6ejQBC7r#3%^nJSOIm5=?j_85j*KJFUFnK;TKF+Gii4+w3NJZ^K#92^CN;?{LT&akwj;j%T^thT(-btdSw6$84cY8XA500 zLl@KrQb*n)GOvIqgh=Cp#CZ_;8)IhDXYQ%A|N+zq4?CzNE1 zJ;|z@@%qL|^*Zk)TMP&R zCLKG&N|#D4bQ1;>DtB4;KUoD1Dq%2L)ly7`b2RK{bN&QywQ9pi?(`>m>ad;# z(ebm)8%gKSvS=?L1kE?ruLO--;U7qmKd}I+dX81G73$sc24Sh!*rfZ9Li%0Q#E&Rs(JAx#yOVEKH3Qd!1bmg zc+p30-+&i&gRWg-A7HEV@?{oDUtUHlFoM9i`sk0&vhXtGqRP?*glYLVyYDE_;|gSa za@y!CkOYoz+pn_PmO(+zHVeyO^1a61_8t_Zf;_oc2B&>}4RQhzk9YpV(&TiTbR7!} zyYb>u5#zvpBS@1RR}p#JTox_8wc!RvR?k*DeNyUI+o@h*#N1hrRLbj&&yV*&UT zl4a#0R1a7O{B+0X3^i5mAbt;XWInxk4?L7dlkQ=mvXgG#V^S%veIElai{8AiHaWh% z&ni{d&Cj$4%iXR9swMz7$L)5h?Pf&+wV;sr(8>F(hJ6R+gv^Dtlio77?4bAus{Sqy z*h{E!`2#GQc9Qo)Re$S;>TTXbsA8w-z(eeo=A}hF!nzV!J3hwq5PkO;i;9D^;4zDj z#bn?D8>=!^Wy!!ls9htR?co=VN>9j-Snxl1%#ut8C-&!9)lQtnVF{VIjytyO)_4F# zDDXzQ%B@Wy8IF&c>f@z}kGW&VE?WlY!{}ED+5&P(=H~c#Rp+MWCN6jEzA$kEsHdB_ zB=21lZ-fXObQB2Bqr{r5(;lo`U#+hSNq~onkg7t0j)ZxG_!Y@>q+@kGP-Vu{&>Q8cq#8fYfm6jfYipM5a5a z;4jBShP&d3?eajG;)pFCXnG!*Jb5$wHtqy_W*vh~S$f{|+c9@Ap6cR#)UG5iYfm}j%#tvwq726P{E~bNz~6KQYHi)Y!b#RSJuiZ;_5@b*iQg~53%&{br_O8 zl_6PK5~bZ~P8gS~m)tNO*jDF^MNZ{9Eugiz$f)hg7ePU(tkaYbx9IG(9oehfl$An> zaw+htgahUI#3Fco9E^H1f)8;W9mLFZ(zRS5LVVqi;7O&I1iBgFK0YP2w=E*xO2-OI zdfK>1Ueg8Pz_Mca0$d~3$I1sIde==W-{|aTg)v#^U5jW$$&_v5RS|sVv5kLc8j|)M zvg!i)Vv<;wEWrrl|4%kux3 z%r{n1L@dPPU`mYTVZh_{SYET#MBIug!!mioZUF&d#?2J7W5MI&>7Q8s1Kd>}#qk>O z=6Z8q*)Tc~2bLODC+*b00Q>Mj+}i})cwSx2KYWt(=mB*8ny+JcAGzkxq60@+QU-INbRph9l^q_?W@ zkDm(auPVG^)d>nzrZXsad7BDDWluq&S=9m*4mg*y*DaAQ#D*qSeFh5Q)gS|>QOjzW z@}|@1YM9PO(vE7pOogXZ4zE@t2j&;$y(S&jvaqcaT%EsG*vb-xB*0Jlt~&q3lJfIt z?TDT!V<`{+nOtk|Ds5+|wjc0ho>H09bbLI=`v^h-_tYTVO_XoV5R7xBD+ythQYRV^N+k(VnEAn&b_m$RQleqb%$>)A}~ zQ=7+jI3UNA(_nGIVDT=4~;sJnHcAt|Nn( z2la0BjF#`M!+RBWc#4Dz!8 zar}Q$Qh`RXahqlD1sC?7tJTlyQ@rH0Y}* za$8|H=i9saoy7mr%`!~(mAMpY@MdPo{Lksz8HO6U*~T;Qe`FMNWA$eYJ0&}CJ`MAj zm-J3Qf&b;^BV78khy1n|{zKo!G=4_kj%oa#`gXDGTZF81Ot1f`Z_OivD8BwPCav{N z`Df;hgQ;ROUhk>gm)wkp*r%hT?oKn?b0l(FRx_yD@;1ZBS6ncU7R+UZQ)>0ryqEc+8_j8r$tsnOwtfav__yIL zo{GiCZFqGAU7y{C*D(QPlz-mhdQ~aVMpW$tuvo0;9D_Rb7XTxs%ifM0J#W%2w$7|y^ zxwJdYdy{_&FWu1YG4keAsZbY*YuKtR>=Hx?8rS&HE5y+LTErKjP%AlH73YW(y7an76IFH6&aX zbm_?uOU$wjXI_mIXu@uY9gUX~Ru4NA`P)tXw)(%|GrT{_d-dX#eSiqoah1X@P*h{sn*eKh!br295dhi8^XyRrA_cucs{|$fBxm})5 z^ugByc&vHccT}lA{{(v5%>ED{`IOgR*^qAb=kGtaxI9N2@GYO>obk!Nmi0hp{rxRg z@2Z-3Hy10ntfx^)e5pk-vApBtfJxq3cAQ!!^X8`ExOxOb3Ham;$X`6Nd3 zZ>1tNXEZD`6X=)G+=?@p7e-@V%b>_H&?H7u=P~H63>rNK5^^N%8N+*eZ-gsnoJ)Qq zoVcEq!ozUA2Cw&Qyq1sU72~ocUI_o6f}P$O-?Cl-TBw{+Nk0Ehn%j2qneRZcvbrNN1kBC8Cz7^MA{zQjC4qFFIA~o9#lov z3|caoSEF`QAoM(@pfQ&yWD1ykURu%=9&CzGr)>eCwuDk&$`CKW8P!l8V_iO#w}LV5 z-c+87NoeXc91kL-?`NSy40bw^|NyDDj0ORUC z@PPaWsWptkXYkpsslk?QX_+&ijv-EbR4SB=;b~h_c}G({hggf1D8*~B2B}^aD5Go{C$TbZjOTMO1jXAuzdBGa`b`FmMyHA?~ z8*(~ro5QC&bMKRarT<(^B5R>(8L{x`D)ZF9 z`EVZR4KbbK_N*Oou29@H)0W(>ZBY7@34YX-ZK~TP&zY@fA}8| zoVFDsAX*|APdnyAO&v))2)nKeAsO-s z=tNIi1SzP-K^aKF&_zm!c3-50C^A$GRELjCS~Q1Fh-F^rj+1M70<~WWbjmH^A?V?T zOSEK_ASq)hw*)H5>SHgK(ohvMt>hn2i)G-?;c0IygH{0~{#Xtx`z7*S!Lz(|9jOTn z_YI_@hQw)b3OKQhb6Hnq6iQx+O$m*86g656!_Szs(W|+;2^~LS4gVEG{=Kz)m%n5v zBSkS%sAWQ0{dG`WCFgk2%#+9Y$`(IqY7#TTz}; z(-mv&N(b2{(7ALl_bh6<9tPc6l(rt~^cwnWJ$7iellKPx0Y3KKz$<$u+ch(~lFqBp zu?^VN8%WU`d9>>lFSM|uA@$a6= zV@s;(G_*jBW|yNATRHTtOdij)b_m11n~{N0ueHOXBj0ZepP@(o@-0~3VC4V4mCule z$T5VcaS3eTr0v`j_h)-;=QHtGxSh*mlC^h$3kK8r9lY)nWT?KAhk~+gck*}TFkicq z$5_(~gE=a9uzI)=2&V&Ow3v(vQnuaL$-5WybOjo`i`SQhx9kE*)9K_c>_)7oDp|Y? z9{GK-fFg0_!MODinnatVhke0y3p&@Wk#)ER02WbsL6EDJ{LLI3|ki}ql2 z?56X3c$S=PS7$@)rc>lztoZj(r@h!^)9qejVZM+E@~A~UEOW-}#iX!{*6oG*wU?^x zgYj!0rS0QJ$bK1iLC-EaQG0cM3{`qJN97-p z!xKCUfc%_;X)2$_eJY~JBbWQ(L~?L0wj$E$^<1=QGY!fGJx0@(Tu6d3l%I=XIF}ax z%4_4K@R?sBJV#UXZz^r&Z#H$6$pDG;WwZn7e`V891 z3Sa5K)kAr`$cW&U%{1U(v1()K{z1MOB{$~r+L4Zu`988_cgelm5%$j;Gu5vYa7bxw zXj3RPI|ST*qi%;F`gYRXLp;-TAno0JOnM0Q@agY-HEw?_dl(DD-PGeSe-{nTIt(2u zlO7-DEj-VF)<*K(6l#BjSM`Gc^QdIHVP<}Ewx4yB$56~s?qA*mfkMpjcTNIEbZZz{WuTQoA;Njko27rse zs-3oIPZQAow_rv#d*w-IQRbI z1wJDZT971-H}l5;_Vtn5puWK2j(bnbYVy6vm%x*M{YCy6&`r3+d!h}KFY!p9fBvp&g_-e}n7b#`8DO%%$Kfyt?u^ z&ZBl$VDXn`mpuCjnCv0>7^h@$-eS}h{vj~Gb49Ui;#EG|eHsLW!@xEExE2LICx!w6gPMy*Zd&MHhS*{$evDr z-cZT@H+i@Vq!FbI5kY219pff=cnkHv2@$=8rrqSRA&$CJTxH#z<*;|PWYXcAa6kB& zLT;hD-zo7H7X<=B9|q_ob4u(yEx*&Z&guE;u)s@>bPuFwARR1`e9Zb+|u#|eI_N^j#x zcSU+Hq(?YtGFhd!cBJnqfecHXGo+{ttsEJKnvmfVGN7#`@2b|7zpLKb>$msy+vvL( zeurr;-ohMp^_Jvs=73bva+ppzCwG_0O`$AHjXo#9a)e^;!QkyE{i;lEY%gs&N*(X1 zYQMM#Nq3AU-{bE&E3!obf+=fH&if+PMbIxI*Y@(;rcQ1q5at|$PBq5siiHFJ%8%s+WPQ1i&y6BEUUrjZkuh-mn!A8jVe zOuQnMD!5i6=cw z9{UPLy&be2{4&t@jbxP<@B`7R40@(Tn-wfKtMJ-V!YEf+dkEP$xgo ze=mLJCt6~aw#iS#0yq4jV}i{lyEwJTXAjgF{&V03omDn;D>x z%nAUM96B2yq&#I7Q6AT4x3%EoU-Xeh;J~Lu9P63c7EujiKF=b$LoU}UDH{81{~o$V z1X>M&{9Q?r0065?iVArAQ4+xSlV>RrgOe_?r9>6f@p>r{D^)B%+z;+@)lCj`gtbIZ zLV@;%A@MBDC?!7nk3DAIyPP@%g7uu)q%_qJ5+zYpyC6|P&m#kZfC73gNFtQBGf0$i zll$J6!$hpU_*6i)oTDFwNYFfo_+gUgas?QA2ldBMIGE$eq>8izM*bn(`3GYT}Eao8>V= zFA=W*{#ZoaD*$9Zji?}+d24HpQ5$=4zw6KDcrYdo=f;cj-svMT$^+C+-Rtop+DE;Y znXf(!jt5s`85b|Gj7!Up7r&dpA6Uo5(&36iF3c`g6g{IatCc25<)9|`PuWMCzN8I=#8f?jqHBql@c6VA`hOfvt|g+~Rg-;bTpg`J|5{6QLsI41V#Kps zFPYE$(`|ZO+ksUO4Xy(*kMLD>K<9qcEM>e)aQeSV{dbqg@J zz%48ZF0v&HBrJF{f|k}3zTnyo^+Y1L_I^D~#iPlnFM`2uuhbWNB){>7LSBahRtuv( z4Kd{@jt|Aj3uzn9fqZlaciao2Dvd;s=i}vmcN=EeC^<%3Q&J6x?~zpH6LfpmL{Y@m z^vMp9v~qv&JBE09S-b|-|5|A>5M-?=^=l!W5hW;jF4&Y%;sdG9=w-?cLu|#pO=&NP zPSB=&8;e(Q%J7}WqPh8g5G`vAw%$Yg8e=ZlMUNVb(pc<>w7UY;YJs+Hq)%EDrP#leY$b&G z_8RhTDP&v|WnJmjQWOc&`!A(XpZWZPNv*`Yx|U$--%2!j4w9(KeWkp*RFHp5QH5%? z1_iIsv^Hv%IocXBZ_lJQAoVV?wh^VpZU`B9Vj-)PosD4TGxAIIG}KV?(EB}I+JG|) zfJCe5zJhNWdxTQS-}ODsRUDY2bs;f$+?v$m%QI;R~5-M$61uN?** z0{yoyO2;P)tZt72$JWrX_D~0}P`M6b40vr_2edGqe(xYYfX95}j_8y@^i4;RWZaPU zJ{SklMA(Tem_pQsd$I-I@-SluNsk4|naW5ghY$pWfgBchHtE zL_{4=xeJ1MQ@X<=yTbrkPzOvLa_1QE?EoEE(2*B~wW_KMRX=`V|~l~-Ay z^eT&bMM$r*4X;4;%ciTZh%U;1%wPJCz4WRWWy04JuZb9`teRdIfp`sm9gX~nYQGLC zkWKHuE{a5hc71|}AY*Nlx(L6xzka}81p?6*?z+0b_vMM*VC=fq>>~PVy{jWV=mMz< zan%(}lT9CV#UL3>7rR0gJ4L0sf$T%b=q4gS_HNz8_S!{tV5OW$sry|p?pam)09nv9 z3z!Hl3&t9-Ag)kPx3RcYx^R&x zgqHtLl!Ebj>;J@;&&S(zm%e>R&9!PKb9q-hJsxs_F5;3hX_&Nsv@0?T#=Qq+Zx$uK zCz|0g>^Rh50tfG)d!-YXTetTxer9m!nd+LA&KWvi=HAXe7M@p&#-_Maf%3+RDu-|2*A@a zi;{YZI5gu?9}syK<@QvMcAr8ZDDs!VT#)uDoTEl)J|N8-EUY%=WQ|HLNCC7Y-PL{T;w*6ZKcqzX9X?N6|%R~;5avp>OX zl~1QX5r%VjVQX4-mn*tUUJ9YQt8s5AA>Y%q-lA6gydb${riC9QFS1BCuOKbW_4I&` z(87Hz!|8EvQAZl|FtaFTkW5ejwS6B^t+1EA?}O=f9xdvldf|Y6{NFmm<1?5Qo_0w< z0WZ7nybTX9?2Q*y>QuKh#F@`peMJ+`g6U{*Us2u@a|q-(CYiN;mF4GfUlCrosrH~q zmWrPX!LeVWHl9+IZKIr|*8+LS2Gr8)4Xjx||J(uD6OiYl7<8`e&mp67>E`F6y2ioP z0>S%*NYK^U-=ad598I_MMBp+7RpBdBr+%T#ZkWw}d_F16leSapmr9wpe1-ZIqZf*+ zu3!BpC3&ReL-ABC7m!2g>es>#n_iE;#*$Oj5<#8&i8e8Ml06WBW0ug+r5PAEU~9HA zNkOrtpJ0)jgP8sNztrN@tct*{%GqrcJ?`k8fMzoVUc-8(;564nx`Itrh z`iq9P!uq9CnHmMfyjyuQYpcx3i^>#JDU%{jJ}zA4sax6jOk=G09Whe zya7tsJscovhij};gB_Hc7VKt4s4z5#+J6gyHx99$MYJz8R~I!(0f(ZKL~QAFh&-&A z!8=7LM2EkHL29$i)7hL7Ofg9iZ_|^6cOeM$2n8gIM7o}Y*?zP9{RzB(lafVSoZ;J> zEJph)5v(a7eR|#>i0M0pW(|Z%ay;!D2wnINO&bJFXFkOYQgiyXL81{2kiW-0nbN^M zU(VeVsQF+K?Si2r*C@fR15K8RG;pwJOqIV7(ZOmkI5g9O@pXH!B3ASer4SlJL>mWy z(x!>DV2Beym&$;5a)_`to)m1~F?NxL9o!a#fh$kIYTFMYJUcQhP#JK25PWH!GK5=* zntTVzPV|m`4AqbM`jMp{=k>#TC_0KLeyA$YRzG^_$5{PXfh>*5j#Z`#Nd=c!^q)K& zZ^z2Z;>eJ$GN}6mRg@Kb22WrWG)z@eLq9s}$CvssSwGh6$6@`rKMZ4aGSwa~>W5FZ zBXCY_4w-T51FSZBxjJSzw8Fi#b2yrUeZk@2In@QszBni~LaAF#M<}E5*CQ}D<)+OV zAuMLornFTfvB(V>l$%;wUN-}WZ|UO=Q@*=#FNY#Wi%|3Z9I825REoTjQ;-LD(;yf8 z=z21l^JWeW94(re2j|Ksf?i0ovT^6h{2o0SZU!>$=Fp?jqJjBV4mB8q8gA#%D`P|# zb8;@N86zs02j!NXR+KY8&Y>5_;{8DmO&Tkh`C$%i7%Ps!hi-C;=qc@_ zcHsm`?6AVR!3rBb4g{Y|mha1k(o5sSA7J@vKVUh&m_GgiGI}$O{{gG=`IP^IsO&Nd ztnD)%l-fcK$Aj)$=$rA#w1sAk7gOLFRDS~Ih57W3eB{%Z2{5{hrc84==`)c#LCi-* zvj&xILYpSSGPaBICSt(tB9}>GxIAn-dXlgP6l^2lLOCPl6lF}pApU{!C&5fKk*oyO zU=p<^u@{h!yDG?)CkyEj0m#+pcGt2csrrxNt|>pQ;uP_kybERYqp}h7(^QmPL;I#; zi2~!om8s$rXok z~eJ$W5Ka>9xk5>p_2<>u$aFH^JzY< zT_lP)OcztFPhG z2Y}7ZBJ{g3qWc=rpBp9GF|PxtqRRD-xT@-BJO35f2c>q1;5;O3H7D z2mntLvmwvudngM!&Sy#SD;sB&XfChx(QYvro^Uwqu^#$B&R*dbi0LH^Wf(#@83BC^ zmzI7mRDT^dU~=iJb)tGtq)M}OcBBp7f*Feq_yB^d0|F%5hakR#keu$sdja82_H zPdvS9nkUGoJ5idbQwI22(vV#{*C1lww+5CWXk~B zLQhTDB6>l9xNH?Kg$G!Dap^`X9uRg6(J~+)ahYTQs_VT~d zhmnIVBTt;Tnm|i;i3;8@`kU}x2@x|+?ZN@405A{ElHqb?zbx3z0;oY2@UYPPS)xK$ z3vP*!bwI80gE;{Ffk#k;6(^=lN;P?0qK{FdnW`t>rzf*G^D#D`EOMgIs7m}ikpT~1 z77R4$N>)*u?US-r3Nmwk9*y}0!r4N5ei5%Yck;g%a8Eu2^N1)Ara`oLH$?VGTAD3l z{1IBmJqgOaav^FK1tYvVpuHd7V zS5h?4iZ#L=?ywke@DkiFI{JR^C<#t49QHDwEA812d)sjOV?V4TYsi`-%6m->WSe(lHBzox=+_)5Y`8oo2Wnpch2>&JGl6R7if(oX#|OR+ z39%zrR4r|>mQ{>JGEA$HjK8m>WGDY$vD+U&Eq@hb@%SB&=W~L2#ywj08wQs%?PI9U z0pSCTnjXMHXas$9K)n8JP^S*SV`}xnq5qGz_kfP7c>jm9yXkckQVArRuy^i_5UO+# zE+DiF|#=Yrw9-rg6zN8(<0=(0)83EDZg#|i@g`fyFjr=|4k`m<%mI1|f` zH;*$FnMYku*s}o{!%o^8;<*oDE`URW38q%wO%3iWg9W-LVS*p&{wc zj7>HC2+@W!_9m418)&uhu#JW4W!1z}fWLXv|CD_KtPSE$+oy$YmEE1~p9<%Ir2l4b zKmlj$i_rg-XYAv7yEi#&PY98hXAHFoXKF;N&)QoAVJjOpAT;Jz`-}9-IeW2S$T%^4 zI2tn>A2*z{hXWz)I|tHWEC+VlbKYK_@I8>S&O;Xt#RRIvZQt|u)#&Mv3xE|PXz>LW zB{>dVfb=6|M>MTV3^6+B)StURpmT@EYfJ4}C|IS7Z+F4-%E?}@hgvQs6$FdzNIa{B0! zy4 z=3ljE*6>(rMv)eMKbTN3eR>9NfPjvH1`Yn8UWW5gr>khbk%@F$fOQXjbPd~eHLbp8 zZ)v{!wIldC456?eYuvCuL{RNd``1vdeE%27nQMPC{YNeS!gi6Lh9Oq(rhPoD9*^F% zH!~az@*#Tr9(HThdti!SM}5!!P4EJlkm-w;KlNKMZ!CKU;57Mf z%;05u;ct6~nz9NYy602f@0X2mv}d&NP$ba6-dIak|ZF)Hw;Bw2V5tJ+KFp z`98)!okrZp`pu>N_rVh4kT!dOLt5d1rQQkLP1u7hK}W>(l;a|Mgi+9-@;7ML1>!gz(! z7gjex?A0_BM)wzJwnbsrYS|f zpc2d;n1gXhp}K_9jPHH}wPOe44OGW#;Rt@CAbyHhBqywb>ca8ojO%zJRAR6m&7mx)pm zu$>x3DXogjH#ub%a0>46T`ysb&k>~r^Y}IvQB?H)k0MGXj4vfxfl(E;idNo+d|+9$ zQU~uv-i*c+{4*ZCR$S5iGx>p88;wa;D$$}?rK0nK(%NWLy^!>x3Ixe<3Z9a6bcs`h z2~yIr@k&Jo#YUEi3Cer_p_y;zKqyd-o2f$BoY`~T3b z3H)+!Ja_ATxK#qX)IUwB?;7{nB&FlO*I~}tK_iouE``g#W>bn|t4vdr+O*Q9JX_}@ zY10&e)%a}~ganniKP9Pk3butTj#r?ONDEW`OC6RQ-wmaV5=v=ml&aJOQ8YAFX%|wk zucD}Zx{^wfCH}3leww0za_L(_dC4vGc!yx0Rg8z~=bEbNcBNV2u{TzfvJB7rC<UCX~XXEobqgwId?~4 zmJnG|=~j5wPL=$(!z8Ea9LvcP-94;aFvM5W|H}}~qc+g>bfvY&vR)~t1k%#dO0?J7 zMwC&?v7-hF<*M*$#3gHLSw@KtHAF58OGs+)x?On@bF!)ofT~>VL<%dbMB?qf0fxFJ}9r01EQKzUTNt8Rbia%hN=@Q zp!i%WT0yqowSoj7Ybz)<_|AC%E}%&;ZNQnbJhJDlc-I*8#VN`z4xwLNWhJ z<`DvYT1zFXDCr=#U$3IPfHIS+D5d$0Z`e)=3IFM*D#{~({{vMOe#bks8iIq=fP>*Q zpqlb3kipSv5|t%ZS4svN$SzZ(Q^=CKQ2MP5NV8;Us4@#uEyyBpdpOi;k2CKf|3wutmM=NbfB(0tW#c4#sYDq*HT(pQ3m&)nb@1Q1NUDYG^&=; z)#mC^Jol)Wfy#5aN058Uhr5f`{x^gYUPnnYKiEZiwUv*s9%Xc;E#_o|{%=QGmiv1< zRjuPLmxNA2Ns6}bMx+!+S995gx}3754Ins5sVlehr*#!}Vv8wFqBV7u2v`m6M9Oo< z5anE^20Pz7_eCwMxt3r^yRdG!anlg49qQGS=VM~Me}h}WFJg4(*YW78;mvmts;(hA zeCsQbWy`@Xz@fgs_ zIZc(85w0xQcRW`Uo5|gk*i25#N6i$~=;#rzj!JmQ4}vdg#vPs597Ka$hhnjjFc1jP zPjPlXTa5Lm7(OEBD5V)_+=aBIx$b)%0rTPqaf(nM6((wB#$cJ2usN@?+UQX@aP!tan zp*NITfKWT%P^y(hnIM$O0-|x2iE#>DSnLZ4gHxas$S^DjFN;6_rqTwJGV)EOo_YTW zI{2pYo9Vb?d0Qpa1cTTO?UWVqxIYnOXt_)wumcHp+kuRDOF0OUQ~S3Sb_zfKZDo2A zWK7t9FSBC`u(?`gOB*Z;GyHfD+j@{%wntaDP*!_ovnP6v@HEYo+p=2+MY9ZBGL&BE z1V-UN2jHpU^tgi($I_v9lorpsqz}=_MO{${REoqdF1;ucET`BdkB-_altv zr@R9Sc>}HH;2{0{j?%!m!Oy2tc~?os#~0sKRCDeK`uJV2#H(r8yGl~AgMfrQmPvfn zCShv90a()jG5MO)=696_TJ8vlI?~`cKn{PlxnTUcT!!CyF?vv;qf#Ey_Rg$JgQU+E zMBO_oL;ig(aJjHXC$Ol)X?iC)39C9OUd~mYK83Jq?Dn1{2u{8yi`{w;ob5qs^*&g3 z>0Kb&!b2cps>J4(T5#ov|esexM}b(S`WN@JSTRc4&qRq29iqdo#xdX%bt z1UmU3{rHhG$3qF-UBbovP`3oz*iz=pk1>j4G-im>Is8;GI(!OA#+pQag59->YJGx{ z898X%C$gc#pD3T9F(~@sPm_?oi9Gc-othGPu*q7_L)p6{TWiSsrhFLo0N9?3@p-m8ughwU-(kK zLcdhXSNMS0dnhUX8?YO#^QcJ=cSGU(IUC=_GP-@Hhw`EUK$2mOROWLu;vD(+pUZZ) zeU7!5OOHNxS3yI2%9IH`<;wri6MZ;BM|&z=0u4dg>kfUttxdP~WeV4{#oT|Ei#o>!2v~>oBu329@0x6v9~A*%#!sbL(YBB1a|+ z;Ef#p`zaO7Bco|oU!`pLBu<-zv@n1d=LEi$Av@JIL-{;#i=2cXBYB!jg>mK$-kC@A zmzk&ZSL$Kc{?=d4CGU9pdVox!0f5vaY1aUEN_bWj>dA_7b!gx~%wvDmUFK?mAlx2Ah^g!v_~kR6gg(cju@#L}_Xi z?uE4s8meSM2{v}9oHpzQ{@5t<-eA&A${_esk0k-C31pIoNOrOgIASJ{l5tVg*&Mrq5+A?B?nj#a7>jRj!MqxEBz*R6)T z6t^_|GBTu5sijI3y*o~^JK^|E`E~zv#Y)@8Da8VI$;uwMzlKY@JP>7feN&5p=qNW{ zc{RvARvtwq+BzN#{7yPDUTJ7LK`9fI&(Q^%pmawpXrj`er8^@gDyaZEOC~BE0}O${ z5sH|ow4yEq@^BTkn+!9VQxnjQlcanCxqh=rN*^w`Ym%#AZ9EAL)>!72OtVEkh!;>enX{;5hZ^ zN^#1Ws>GPL1yRju%Eu(8DKXg4HKr-UJVuQg-wQ>_1UIjWlBM85>Er22rpFq~mfxG9 zL>d0%q9mT-#X7|O{fKVOP$C1?NPK#NzjQ9bTl6~cagc}Jms_Lj*-DI)KVxIBFgUi% zj-gY#(Y+ihnWJbyuqiGWa2sA|YnYx7RB6(kSmi*DGBrYi*eL5z+3JH}GR;!nl$q)G znMxE8$KNxR-rlqK9<^Mg_*4EYz=}*<`tMuU6EoaJeytNdt+nhCuW-L<{L$lNTJLLg3dXwc!Qbl>4EZ#+h;?39~ zC@uKZnNyhJ$$)W}FTjaE?ySLnCIUZwVPZdhIl%KqI<{P?U{J$Q*-^|2a2Qg_!?8Lm zKn;wi-YbAUw$P##kXPlvm4H6P^9W@ue|Ha=_8g{$45NH!C6J?hQKpJ(&OP^x+yM%M)#TF`+?hWSFs5DN!D} zsO!b?(uTfb$4J({y03ik1&l%-^-cP;&D8k^<=Gd2T{V|ZKQ!9=4%ss*9F+^jgqcdN zgKA+otzDrzcQa5m+*2fNRFaeAuEDiXD{ebM6F49N2ffj965{qR>N6f>~1^s%Gv)>R(!808MQs*`+wNlPV(*X1|AdItd zKVfR-8X%+JdRvq#Pqr~^i}Jb($`pgVndB^r!v%o^O!Cl^RPdre5UF8S*#8D^RXVc$ zZ?~;VS&Tb}gZcE+R>dABojOAH=BuYc5MbG+l!upwO52oLya>IvDdqSbqhLxoSc2a% z+OSRe5l18^TnK9P0!$bRR;Y&mCBB3;bmA^0+F(jhD{E-0?NE~4AAIql;|}F{EW%`b zNBQZyfU$nwfyq2icXt3&UZBLCN-1{ zIjdkp@4RRTa=KYX81>nM9$kjP6zG@Bc&%6lH;f=*uaaD_f_R}1cN^;CTXom;`{*n2 zjiow4X_gJrG1y=jkp}7VRXgXEfz|BVm}gaA#T8_GSL)zzd%VA`;ctI?e_PGp)O}u! z|A24K#`9(48M1Ntn4Pon-R{O=2Z);<`;??`NuS9Mt>V}7(vWo8LMps zU5sF&5#(_&i7p#K+|Ov}FRE(<3GdUI}C?|0f(;~Rgw&_ z!j{YW^8hRH$CM=Fl;RVE0R5N}4_U$+$Dm5XlXytR*<63@ALPX@ROAH5tF};|5uHT^)TR<`SK-%6wdqO@q{W+9$QK{(ez+Kq^_`k#MHtvSH zI?&^ytZv3dS=~hr&QpayWZP~30F8N>djA0p&T7j0LvBIKCAkIDE-51njH%JDmlSro zbL|qcU!c&-ik9RWdA4-PsB^=){+K+SpL)1Jt&s;M{&!iHm}JEAjM%T9<@d|-FL3!I zvOIf5y+HOWvV5~EvV3R6+$~<0CEz9r%Oy)B%MweC5=V^^w~bixRq!nPsoGW0-oMk} ztC)&BT6$Fu_wH4kzx9-S4R$kIsLeImVE=0nD_o#CMr`jjIX{=K$+@d|9eY8#DZ<*q zgb@3!^L5bSTWB6qFxvgsm6WhkZgf)$86I5+X?~h&-tZW}BQqTZ&dh+TLMU&~UI(9f-4hO1Y)P(8^nYp$jPgR-q<8 zxn0m?%R92k4tHdeeecMMx8Fg_H=WbrD;+yMIynj{;urImv>R-6m7mM zM;~=h2JP=*-Mj}n>LF-<)8EiPIY)c*Z^i1~8`;u@Rt28gh0@CwR7{xK)cdkSUGEp_ zP!4}8=n#{VKi`)fN_rqW^uYt!lT}9G`|xQUI_>Jqq(^cZ=0B3tu=SB#yPJ<>4Rs!S zwUmyQdOZd+cb+yq=H5*R6HknF0*U>unzKxTPhgHo@PS=t5)2yx%}*9#f-a8co5lZ( zf@##;A|ebQrl8M`SQ*=w<=epQ!}K$YC{dz-kXu_o;+&Eh%eXRrZxN|jhZ7c|2-m^C zF0+)D$I$7R#Z3VLaH_t7@!5yILUR|%isa_gxd;nv8PIwbaTrDJp@_T3OJ$K#u8vgp z6YX%2C-@1?3ubQj!-SltD1X7{u)4n}8dgAa7Qs}%<1f22+sLq|aE6;m36V}d_;B+8 z0%Vol17wv`0z?}${8xZr2$B>i7+}5^C>Yz!4wPB;1j@Df!$>P1@Ir*TpMOv7$MM#S6%a$&82--uV9cIFGhD z|NC)rr_6~HObYILGXM2BQ5t(NIbN_!%qH=2D~^koWe&u9oX|-{c@C0!4zi0DK5oSl zo@lp4f~;d?f>7La#RgeN64$ZasKZ599DK64e^HP6cn+)LLzwG;hw6Sfh94JwVjXLd zU!rTPX_5J|34T{O1G)lcLw-sW0{i1$qDS34N2Q8+eBj33_WTfv4`Yix(Ue9&l5vz) zT;v#Qsa45Jl$)`jJtsMrmB=$!OadyI1+SC4(K^2^Rx(K*h1Zh=qyLFXa%I;i$zyT? zG57kj5FjF1Fh*~eECI^AWVx(+l0}MFu6xO{O4TOn1Co7glU0)KiCmj(g6Ro!icBt< z@IRXiH#lp z&(ZtkWNly`i_@%f;$yy~(4f3fs7iSe22pVR@@Vt`^(!xyo3D@NOY3%OQ$cKj>&c|& z#UBWQDvE5=K*xfLqLc}O=3gpdXXQ8^RzfR~G{;uKURXh|R1y3dNN|T#o7hdnRdM&3c)TIUr?VE!_HZD|&_SF#OP|{RWJo{$3 zESXtTlujEz31V7L=`M!y6lw0PT>7o1U>C5%bx6N5UJ&nLd{=vbW_t93ob=FI;>&*@ zo_Xdx+FeV$Zw$>wFV_~&zOOEO`9p2=a$^=`(CHpB=%@D*4%4D^S1;L^nL8K(7>tJ> z0Tyv{$_JN;D%25QVnG+z5zC=Od8e*;*?c#KR@W6OeDR&C3$!|7Vm+L;0hCrxH0HF= z>xo_*UacqCDRbJ3q76p}z9>?VYtDm+p!&$Pjn>x}O<@Qf+5o#}I5lY? z()>rl{2Mn)zHA_D@_~RMG^2s2gRY!uAR3xBQOSlvHE)W6KS}>s>fBI-75OH{cst%l zZZaG>>l_-^P^3W=wxXdZ)#3?TFMqbOLN1o7u}~Pgi>nNn;ojNCa2YrI{B_OnBxqc@ zM?4ENW8_^#Wf}>4vZPZ{#PCrMsi3@!kx8ccP|a=O@ZDH(7L9$y8|OMdDZELOIL2vOJV4{=z3G2gpE|WnHc80 zC=F97Gn_$+B)EJO0d&0?_HG6}Y9`p2I=;E6X5Jl5Gn$LiG@!Xi#4=8A4v=$zerql= zO>m^sLcCcyV+^=3%LXVeeVT{)6x9cD+)r=cU9VlAnss7Wi;|0#y)U~x>UU5cikzCTS>9VH!^Sx=lt(9uFN|geexasVS zk#96JAF`M(wgx0zLV+)d88A4^eM!`0M<~XvN5CexBNTQ={qQBRmeKbB5lhciQLS|P zWk9rbl<*4n;7Drw3aFyll=+HyC$K-?Cyc{h`|}l13w8wMUj>TEqaLpUt`4O|uY#2r zPa&^~Qs&jswB&+4hMK=7BH2F|JdOeCzyF$G#oafriK+mghhM|O&7-@o3HGy6vyB)F z-y8eehp@bTw2aX>)1wFRAk zS4-MT5_3>n9JI-_zOCpGG8dkuc>h^oB3-hbP{JNY!-Eyf51=5y9&Fc691nSfJB{)K z)FQ*%i8Si^mKX$ACpX>_TQSJhZ=<^5)UCaUrhxW1%2}kpkExNLszM%E5Q`>L2V@xQ z^{Fp^8t3)teg_eZneu-})P-*s&+<9%U}`3MeJcMh%9GcpCHO?8+M~3yU!^*t*krFf zYdeCHn&S1TRVNgi)uEu+UVOk!Y0nNcc@HG(H2V5IQ5~>&%X=W9rqf^Vf!>B*u9a_72I1abHf4S&o=dnK52piv#hc*_0KQ$& zzJz3f5OVGMP}mJ7!>}g|=nRlFk3Q@Sp638f=`7gsy52>S0bh2Jgm6w5QIXO3+t6cm z`$+gxMpqGzp+|Ma-kw?b`)GW}$(!YRtICb)VPJ{pStD@OQlk1lyNb6=zSQa?Q8I}A z8o}Wc{J#zU2yIWNbstHNv{{vLyV;qD7ROw?OUwB;gF?zd$e*aiv2=R%iUNUp} zn7GuSE_lxZ_7ZxjW{G?cn>B-$9{T0QW8ykvQwPC2gnnoljrc^gX2|r3sA8G<@M|jC zO+4EfvP7k(9wLR7b`t^S>tpHrZh}>t5{1|9E=FSd_I8&r^;UP`^-M!yngbP;Hg8@| z<$8$dxI&uWJA*+G7ooO21go571D}2-KKp0lz_ZFCg{mBKiQ4oKtUyL})uD=g?sFl` zaBSWBb4=+@IPnvWIJ)6;Q7;%OQd}n;&yap}PoV`dM+B#Ac)hDuPtky_WNP;WfM3;9 zMDo3tF+D{wI^PqN;C_ng1tI|Y%U+_ac|DvbwTX+d2Ex`_B2_k?4g<+PrWYvGJo>H| z;Kc#D(o2*vXW}WWFR;d|sooa=qxsbB3!$b0FB#|+P>9W{b*VgyV2@mY(b9bL`!7Ue zr@|PUTT&^E#Gx)`8(=fMbtLx&^Rt3J>@B3z=&ySV=`{L&Z%}y$DE&)u%wUFs0C}Om zjryPPx)|uCaFDxT)c?eDmCs?L>BT$VYa)3UieC|Lin?< zA7p}F)(@A?YxD)|T1{W}g%EE&ZRsnk z`n#{(yea)ev8Ykeu(*&0r;?)x@CYOl-M(YzRLiO2|UwZvI(90i#Kt2w)Ph(F}X49 z(uX~4@buWA`U-?$?1TQI1p`I*yW9p)gyB4zsp_lRX~+Ok)HKHd+-x;*PB#X(Nbs2g zcPgW3`#_+?74-W+Z21`!JP2EL29+NqD#mBW046Yb%a3#;a6QsZ{RW96@bS`SFgD9f z8a5c{b0*CjEVi(Vu#bm`l1!L=GemU7=fI(&M94$-Q;7S)j5I3^6@3|L8Xu5x{ZR1% zW<<*rO&P!9>1|im{+Xh*SJpL|VwjP&9QFKKun-F#*gD1mPlGZH1%JryUil)H1vi^l zIED`sdreFf!x3Nh2)JrnHwKhD;_}%pQ)o45`#yDq7!6~teG|ZT)Ey~0;Ws{|lQj!C z`;UR0({xry)kIUAej-xTn zM<$K~jo4)zoUMH~8erOJ$bp8&6zV42`TRTvG`TFqx8TZ*6R=fw)le5-mW&hCJVs-c zqv6(~;N53ls*m2UL0F*dX=o7b9xsYI+K&fzLdj1ih%yLf7y(9J)A*R|C^b>+GR0xR zeBmVu)K9+#pLWKs;|={V+7UiU>@g$ji78?M47!JYBX-7Lxz#_;nw?;<6q26TQPw(@ zKAb96;i+5OG@PWN^vX2xlW7oX(?t(hjZT{mhG;acoh}B0l&(8N3H8^qsoipUWjcSdUD071j@BL_!zE?vwKgFVp!o?$&R!gzI= z@f%p-VKW6BFyXz7nS!M%wppMZcT=ZX=wN@EGE1a0+IihFMR_Xd7 z5UwAvuhM;j4gV0ZLT4DTjmFOr&wl>I!p%m_752b&^T13e;MwAC^F%7Op9^Z`2bwZh zJp1OWEE_&gJeT(C*OGGfF!O>pufmWNjB1B@qC42>xU#B7&970Z<}*wN^w3OTV@Y z#5&wPN&FUzvV&@T3#$4!4gXgB#ukZP7lLS9M)MbnH{x73TiEA-$-}O+=pxZ5;=34T z&-~pMkN9Y#v5Tm^T84#|6gH)>bop^{Ip_9evt>q#F#AfH^z|wg%XF1T$YWj1z=!xLN z71*L9Y1#_$73^OVSBmsHw_xa}ne8xKL|_BW(=45{*lEEEO|@cxr1!48u^on+kO($H&ui4)H<^ zTu3>)Y)0o?cT;m5A`zaFJfd=eAr&Zi;{$nYl(1T)6!Jk35HWDSCJb(0)&3D zT7(MYmLV@V1_THdg5{Gg_78=m1hb$4GlO@Rb5@I0o+sVM^Q22((4T#elYVJ4P5WN7 z$M%2py#&nYMm+UhD*}VViM{4uv&yMtBO`R`}>!eZY}~;BM`)^`b6K{87}884VwF-Qg_9loEi; zVIK3vzV3^zg`VdKxds)9Pg!emO7QaLT5w#eDP$dJ`PKB+IuIEnY3Mo(5Rb4TP@mRg zc(6i$0wik0=CXxbf20=cG1#^A`FdIH%=IEQ7AE#snQS>eBX??m(dYT7eb5H+VUwrS zp2@Ytj8{q?0#LV6O%{J%rTG12$p)*U`6|fZf*7$xWiIe~#e= zrq*WRb?4LzV@dGezhj9KX1YnoHv>o&!1dR#r{`?J*3KdSt)fNInM_Yv(k##cR{`r= zyNk^S^bm0NM*3tcV0|8q-zuJucV&av?qy^zsrT z_eY^0;g2Ojy+7OoQgufRJx-HvsK32elNY`VW!B23#p zU~Qr|_KCbGbQ_|^KsW}1Bcybn6o_Ec_e0(`i`wrO!(xnNjgwh?iX2JE@z}^w{s1t~ z3hHt|bi{P;KL9d)GhI4>(m9m$(?7`O<*m}iKZ)|y3Nf<_m_`77Vazl034YL{70L!0 zq3A&=%r2l2P96mJJDd^@p;t4h^&w!IS@hK*NU65ahC{$~Tj~BGAmwVdU7pL0*IKAUV@uQI^*5MQ~O`Soc}HD zI0LQA4^;N7_`JkCN$M8E5wv;vtqRx2EM_f3LdaxFDOKWmdT>^#p3_r!1hvkI7hm4Q zn=LRmeHYV5$4b*w-zS8=G*3h zPd4nQAL3yI7xWJ|p261_s_pkpl%8IK>2K#EaNiv9`OpZN?+&Fs7e!+9U94&66b5qs zUG=;DS@>olyx)im6n}{BQF9YQjO+KhqW8}NV>R0`@eeVTdA16d#cY7MBbUXRphfV& zWJO*`!> z02}O#1Nk1eGlF~FxX>MWT~w-tCyxO1(=1g0{8^oH%7=Hw1dA!CUkM+*Y?o9&J8mj~ zMhqO_z;HxjIj_sRtyl(Kkd&VxT0I zAQtlnEg-KR1Xx|qlD51dloC?nBNfA-K#HXXAV0dtz5pzKOi0C}$uT!XLWpbI`0Q-SY!L5Y51|pg-fMGND?~nxKaM>J+cm&QaX}wK2LjDnM-l(ZR6*^ zEL;?zL^J+0BTNl7&mB#R!c_TsDv-$=^sp$#0scN*Ef4yCZ4p%kB3u%#vS#3LxXOyk zVi9U{*r;^jU^T6Yz)aM78nt!ra)i1I8tpID{U?`Knp(AP#uC2;`>w9C{;C#ELiSZD@rZFQg6oJ^hFe= zdkayNtZQAAS_Yj?iBZ)!Y4+%^SAdKfK2J^E^p zOJXor^XYVqng+|hkXW_giV<5v)rnQ>Ve*E?sxKng6N@ESP0?{Ocr#9|{d83-yRTRt zr{3ee&Uc~?#;Z|So(u76X)mj!bZM_hP78akVao{fest{r--z-jAVxB=ueA&rg!n z&ucx9H%q6QQcd9XEQb58Y}^WGL9faBP^QjyrW%r2?15YmkAV=dJ&K_c$!cTeaSQ`` zu+(rPq#yI?40=Jjj$Dm=CcPTl2w11l*krY)`9TaFNLCZg4`Ex8tQIq)icp(c-~2en z@v=>=W5zuP$D~yCs}R#*N@@?<{|9PPTJ3?@hSI7oekcO80%l5+SdY08PZyq6{fxo9 zsby5J*I^6K^^u>nB-&6$^)t_WMBB=!EesBhUx%Qwsy+VHLW8DqV*F@*``;3+Q@={Z z<7h^<-LI^VbxT97nRl0KVFSxQ*vIg-n%@0(1^9Yf3GY+#(^i|g)Q zr^@PL1185hpz?3br1$4l)t8WWM^*JXAjX?j0gV=uS`Ej16E&}MGDU(CRb+xiNcbs7$_oc4x!FF$02PkhiJg})v{3pQ-1h=d|t*cJNRtc)7 zu0gQ5p4!#sN&Ma&Gf+~vbA3%AOl(@AzNVHhs;SYN;%%1Y7CKXrlN5vumia!&xwz_bo}?<0$t4i5uS zzFhu-H>MQW;eecc^rD*5&zE1)Fr@@rYC|hxZp1)LXA5TB^|u9gMU9ZXbj5?J_|h}Q zH`IsQ3S=@Gvu1^_tTHBFI1+}kINgV}TLE1=L!5`qe33mI8?*r=WB#BiSOj=oj-Zc)3Krw8XD`;FS)x z&a(N@>H2E1ey&PFWhEwb60dy7N{kBFm(!CKupEn>DLj50(A^gLX(cnf{ilRLevbg# z6;6faoU%!Q*)?=_BW4S6aWW?P|$HG%(TUjibK5L@J*Sm=G>OCLc^L35W0Tv1bPX$24M^4m&p|r1w z`bJtl#sPDi%9eP5_*1Tk6_F#ZNFXBn$5ZR3s{Q|veMVDtLBgC^*8bi#rQ(cf<_D%! za~I$eUrfO}&D0kY=E>wtGgKr<9sxTJSMr8tU_0i}#b#uj zQa=k_#Kl4H;40U*^hIkFUqpGW)r-og-vLl9*2P>L-c18_Jmv@UAJ8|JF8cC;xCZM7 zYrK6gsaoLQSnICqwsO)_r?mP?%snSH}4#o*dfv zidv$^b(qU{Mm#mLj*s;&AgFXMY1Z$$z89(EV~cX7vGFD%HX}2oyb9hepGLh3?%)iq zdR0w|GFnWt$d=e=_Zi29SJlBLXbiiy0lPDo7PnD%Lde$pb#;tsi6i69g<KPJ0Gkh*iy8A3ykba>hqSm z6n##ATW!FMd(XGko*2-Tx77rW2DVr85Z&1xWcs(Xxr18Wv}EEtYEe!r_Kx}%hkf2r zKS$!9?;vrdqx8EfnamI3XzYLA5bXx3(i?jSXUgZR|2Iz8+3!zQ8GAE=+8=I9UA5yKkSOqY|U2{J{m~4=yHua3R>6T<8vpV-@9ms>VM5eJmJuyh6l;oJr63 z0Y+x`Jkk;ofP%q?j9zDEM4z-mdZfGbsrof^!=HbqHqYo2htpH{^p$DWVKTz`?YK|wWDlD&*0^n&Yu|LBLK&wRXPs$xxu>2GOFl3MR zz${3*^e8JHU+AgUfFf^4PxUj9;x&7L?B7D$d#OXA=V|$cIxF-CX;lW`<73@QkH5fy z-$-41gQ?s|V|!z1wm9rxVrz%4!6X~71A5pw|5JZPt$q4Hq_UN!_E9hRufs(HfZWWl zaL#wr%CEqU?55&~bj{E?w{hx@0t{nbRvgmHr@<#s>}jqb17`d!K& zh@%eTTgN-~djBPZIfkbZiXyfb*Xt4U3(<=pb`N9&V!k1|1+fDQGC2m?Bnq)PxI%*% z)XiMWNTVFA$vAD#nEps(+Q!V{N$`7>%)WBNg4d(c1JL_PjyDIW6;1ra;@E*|4OVLH z9|-nl7u_GIz8Y|D9o8mmrlZXuaE|cVy=So6Gk69lBDMs&2UvUFI-2PhpV&A*Vj?!5vp4J zAlN_s;U!qnC0M6husT1-Vy80G>tp?e7LQOLLtM9bq-tjI3v0z`Fu?Fm+v;dAMrGNjqwQD~H&%|)=i}5_kR>LJ2XM@$ zisQjLpBPHL$E$Bb@p*W>`h{tqqxl3#HedrXVWQeM@_R5{crhh~IdVMd0MUt^)OH?a zx03n>%BD1kB**G)OS#|V8fx7XA5X=-ZN&<$9Ia@MLvL-gF0q!&wzrjY3n^qr(nr>h;z*Ei7N z>FV_0UomTCOqYFAeQ3;gYGqn619Ack=C2t*R=22PwmJyiT$8P)gKy2xR*xdKF$ef= z3H_0yc1p@!KPC>Cy_(ODR*cQfo{r$yq%-uqf?eE7@F)(3pCOKtvel?7OA*=u+TAiiCV^tUAAKxCInZd zzf(U#knx?GA9@*@!xYKL=Fg@c%T>MBe9SVe8Qe5BGitt1A_CCV+u#n&;+YN90iq8u&*XBc$;m>zI z(tRF)LFKa=08{#0@^z@yKn-vb%$pwr*06R;V3tx;E+G92kYsPC9Dd0A`K7SS^p??*7h zU}o}yjTNTSUu)IX*g^}}0T_>_U)EupPo>25kZ$Kw=k;iM4Gmon`s*TXS`Xpz3CG{- zL8KuuW}`QQ=w-z$8N_SbRMn#A&ZcP_)lU8wW5La*(e*slj?(Fy{!3{%$e#mXEhuNB znnq_fsa4RA#LehVKE1Zty9O^4c#rlM&!pcryV_S>?SHbxyY$n0AE0l^LHjnNefw6~ ze!H!ZRp-;tt^cJ4i+*$#MQl?$q2r%#^HzcsmT_Xnp7UQs;DA-5$%fl;+`%ktS8I4u zI8QB^8W^TOnuYE@XOykF0~_KZeY^uW>MY(%RG;_%o!20hcI{L@q;flPmGGDCS>X!?+JNE{w0*K z7ijMy_1TL_xI|O;s=uIgk9}%=&(@y0byDcgJ~b@uG6M?_!M+JlyO248N&kK}3|7=W zv2vH=HX{zXG~B(yGhW=a>(1@}Z+qst+_UL4`G8u*I5@>zRXjNGU#h@E3%nEX=o25D zWk0#9Npw{ceel0kb6_^ADQ#4<|MoE7XxtQd=CA3n9q@;-p}fLX52si_K5n8dDQRJ@F>WRGc@cd_WK!He^eb1d|< zbb3}$XX|c9>r)_v1BQm-xd+h3znxa6!ASh8Gax*6)ABQF+rZr*Cap+w#GM6JN!S+a zv>^i`@v4ayo&yn)PdCn~v8KHgcwW^LFS;`0&cqW9Q^)gaO5)jq3@jM->=|XB2NivW z_Mcau{dR_g)-^Avn*YIhaD`cvXWvevFQDWVT7N-p>Umh7x^P-xkUkM2I=omRcYMb0 z5^iq&{olX@7CjYZht9;RJ7I43dR09sr&F8NQZ)9W+%&r` zsuexE?d4aR2ka>Jhx)x44A9S))ju#pc~?L!T&B3IYHeImY;zTi&>7luRqcqN{57=| z$i1JphuA6in%WtJbdl@oUJzqvuB-Qv;ny4B-G7cDy@)BER{yC!UxX=x%V5F5<+7vH zR11^|kN;E?1K{Hl%DtJC@)!6Tf2#GD8q*dYi+ccY`$(dCKX@C>Jf7h`bVuNgq#YnTCI#(hxvS)R!8m!cv%XaJwi;IyuOYcR%Of|)zTd-91@f~wf7RTPE=vUP&H?IMNRe)d`wp_cd5 z6pt2BRiPH63b%-kStq(%gd^%FM*Hj*qyEe8h70bK(uPX+@zt`MZ zC%MO9Ei{H_G}GjsD*k1{@XWPWGpL#;Y_hwti2vHy#d~Vnzcd#9^v0&R8w)Sg*t1tB z{J$KpuqRrye&cQ{?ElbK*nepY#DUjTTBo|(V%z)wbd;yx2kA47PThwU%^wu?K&=#C zaKyYfJe|r{qirBBj1`;VZVWCc{##=k9;jbJwNw2ekkKd_`4IRqn>IgGpNqQ!Ik)vz zJjBxg{ZNcZ6AM@(`aMzyMxKe)eEb%Ay~hQ#y_y7m}@`)xvsHphG}mQHR9Ni$yzrNHeW#mQ>Y6yU`s+e1`pXVTsV z;j-4G6@!NEm`P)vHP)<6O}zOXkh{s++R2&u=G@mmK6^i<+P4~!GN)N&?8$%QaxXAKNo3;uU6Y56GW8-nMS}|Pi6u|*anEc zx1UxQh<>e~wmPYxUPw>52xOBIQL%4?AvDfkdl|Lo`)j%{vYKgwNy9tT0orq(UH4)N zrQP$;0Ih`iz)V^gpuLOo)<7-JblRZ>YQ;^kPpcoKUFf$D+)Y{Qf&}@ht{x04{~!2M z8TY49JzXE=ohw35)c@LxTuJU+Ry|%n&Yxgq=Bz6cxo&Rq$`z$2>1+5C{4^$n{ADrw z)3?D|vh6#Tp7`lI&JBeSMTZPekJHyc6p2a5_3exc)_(+RoeV*aygLg)&YL0Hn+Z8w zm&;1ukh_2oVG)fUuPL-YOiObV55@Amc6%do#umtO%=*K7XzYi~L2wg-eE|pQx>XOb zA@H<8gsjG_Z&(XCkf%Mh{%3zsnu=#TizB!yOv10+5UVCfhHJ@C4lD}S?CK_@rC3;! z9+2WI8$}F~^ih8g8~d5yO}@>T2}j4#!-gpigf_#ky;X@ z1??lXIz3D7_~N zl?)@u7N&cj%$Q@<#!nUQ6Gl$MCL zk4J00|FP{)VgNtztVoPjn+FPpr*PXf2gk82?|GKOxhAST=VP00t4FD_mCSadd?^+x z+W_c{St(5&VznXMGZQ&`77(YUK|fe7PD`>b;|=4>8zUU*m1S4y?KmylJU)+1@mh4L zCw8b$p&k0fUf5lxjE}jt@yF7`D&hVni;u-(wuD&6T6{vRS^RH2{$X$6Ir6t?X)!F+ zINDcCD{7r-Y+m%mADeX4-*m5-mR)B8@0_9q2MRi$|Ce3rsGOwTHNiJZS)10W*c3^2 z+F?!vAZSamfQdFUgNhwE)UnK_MFg_3;YLjhF_{KB_NHl#1HtAdl-Ft&pP-q;`&s(J zwkbQROKLDIW`bD-puwaDmvKKUugwbs=>oZHP)eje<-r(ID`?G4k<_z-*4TXgByFsq zl{Q7tjS5<>>1&$uy!KAN(-z3bL(_eZTcB!1c+vv>YOtQ;+ZlHl2b~_lQsv-upKRZh za1LkqLadH(x^GG(hY?{WRv87`5-MAcfa>Fi-NB6o>qjDi1KCf4^N4Nd#Jjj|YC+<5 zBrdYBCa0g2B)fCnwIcNt9E%3)cdebFHn0vi@siqt%a|TS0#F6>D|~k&E14%n@$WSA z^~lN=Jmn;R=i_&#^YX}je^2O-QSj{2@s|hDf*6?9*ZX*%oKs?rT=0%qutAcR_N7(kz*g zsqyS`13X{+JZKG!k;1skx)hV5na@S0pm2IIpUZrO69!}jvzHNNLlRo1<(0H{P}@aT z)&`ejBaqavYCajL%Le4%JvFwP&m$+E!Uhf&TPjWvyy( zWHlcMV1o5OPg1EW+Vjydx}|$HpM3s=PRx3r#q(T!Z;g0Cajdm$n$%TOFt=(s7}>rr@Dp z-V0d7JDi5_HiyypSk31a|12VZ-sGQAj><1+yZ#@S7?*$DBYEQJrecMirn&$XS;huX_+pxFxPn)JC62AnDn&B@wY&3E~znyk}guO>ypx{`M|Ru3+X zEg1l2#!5meDXkSz5D*ALAM|_>PBTD z5hcukgKhB=D!M=#P7W-D8KN08lN!S0+`muG)91!q2%y1A)jBM$p9`Rw^_e_5u3Lrx zD8_U!^nzUkE|3T7E8KnMqbp|%@S8!I*$K+_W2(599$7K;$dq_|!q)l`GbbT7Z}(da z$NB+~0R^!4UQh*?;JdhD%)&GL%)p&sE2vErjMs;lQbP1|08u>4{G=ad4gAx81*)LV zo_hAmG5#oY_*_60%U}5Hm8lCp>IikIt99)MM1?bx=5sa($i(^k5`Jen2P&}}_L6lT zFS!j*ieq_nQzi2t4p$E!6bAt}uNYL9o6VKY5;?K(o0GAn@ZUYtP`ozft&m~NvB~<4 ziC(Rzl?=XX1$lrC_rOZS>uIg~<#R_c+FWa8%PH=N8Ni#r!3O0zhiKq(Bv2Bbsf8u7 z6ZWElrBZhY^TGGkYzh1G}bPfwmU3MwAW0~H^13b z>yBVgQ|&DTrJ89&U)YJGWoI@*vI($?wwcp?rhx!pL>y)UwKKOM3lsP5EbvA-l5RB9 zO2FVDrn%M#!Q0J2r=6w6&C#))6xc%R1ZMo>7FsM~gIj1#5IfL9D~G_+5}n>nRa*j) z@1i$bYP}IV+!90ILouzil8EW8z)0_*iLJDLroE2X)>@1S(NZsIjZJ$TyvVXcg9kbC6PtL2mI~1$QRe=+Asj1dq}@3rW6y=?(Ma2UMCMEj(ZdjP7-^be zHg>^?sUdnS(pDNdMTj1O*cKyA3DIK^%j{<)+KqyTjl>d0!Rba?s?mI|k%n{0wrD%A zfTxDHh7dgnvDu?#ESZ@Xi+*-j2B#$%X?K2*11!$mw?#h&n_#3B3(*4+J2S4Ij3ydc zvvx}pI+#Uq6GINm@g{`mKMs&%jW?>;3i$=9hzrp}IoD4zSFBOPm?=b$M{LG5iX3c?rhTt# z!}0vzn{PlqHG+D-p}lR$d|<||nIZEzhc7Se#{u!O-QnBc|IQJ!}ob6pOhwt8(R?OzRX%Z?BC& zu{G_rm(0^=QbY&MOUdV@n`9B3qkRXho5?hR4!omnM=<4G?W6FYoQC^so}c>@#dOsA zu>J73j@lbfq&e<))NH0FKc>B>l{ayTcJFHqpGc(T?`xl$1~|kAnjf1Nm+Gty?Ki@d zYGFTHm_|70<4ZcYC(p4=Q;IK!hbuYq22L07U(9T;fT=T!A0eCa;p;bk;LXgnxd5&m zx@sElRnw$@sENvV(du(2n3;!oTK0nNUc2gM9fAWmSBdmt;e%$*GBQDwV#TuRXys@jZAM#c9iX~K81^EK7q2WparU`?%R1WhHC>zs8KF#CluNoya9 zf?tFF6d&GvhpM`tlO#5T9O3XE5l$U>f(t*$Xf42b2)n8IFb6l2&Tc8)eTg)&mKHV2 zgjeMoG9@?0&t|cA66Uq};_AuTi|X#TMZy$K4{d!K?8He{ym48OeO~~pagr4;1P=4H z!|cN_Y!2Vo#Ku|o=z{N!{kHzG8GP@D!LZ1XRa0TPNBs?AQ0=j0&oZDQ^E4=!G@@2m z8j%(@fIoLPPBiZ$@%9wViqOw(G6j?=UUqh!S=z0NvO!F_Tl-Mi5Hau3;uKtzGWcHYnXWK~a85)&sCcFp&|%*i@U}Hs zAFpLjz$(O4Ct`cM{e9Z?EuZD93`<=Bwc)y_+1j_t;>gT7nj7tp+&>p+xoyc?;J}_Fuu>+-ehVLP)uU%M0qAJ5n5 zc1Se%K@|A-V(qq`o9IS3GL%_{^Zrh=qU!|TCMKd{vY`W4aGGU^0fU8=uIAe$dM?4V z^M!bMiFRA(hRjDgQ|98%GP7CO#maHAGjd$E6k9$~@zhcXya&V|OSN|Y@yH1RD)dUp zGA$i&^LRP9OdF4`x$+_H3mKFi2`<-?RMar6K+CeMqE7f5kusXyNo*<5Zpt`J6jO$y zINYA%#)+~X(Q?G#mD*s~=B-@G^>NUrGRXgMEa;AhIn^_bf_{=g7q5z?%3H;${<#W_ zqgoWL*6z%xrt0hDTPT{kKeG{xsOxSd6OU+<6XZ}W&Iq`~^t-jxNXIpxVRYubg6Z`g zq1_mVZdTCEMxl0d2BkO4+E}eBY}2&Z9P!UWZMel-D$+r{)^&4h)@o^D(4*Q6D{g<< z8FAIIxO&=cY@BcQV-5N8n#R2frS)rTwZq^RJJxA1h5kW&`2-ekQIWqME5ZZfA139Q;Kp52uo0O3MSQjqIhiVg z7!boZVG;O?DBh&Ki9;JxH*0BaaCsu~?`g){7eG-S4B6@A53cdqtaZq&!eip(XVyKz zbWH@qrs3lTUO(FmaDEZDJShhZ(Z-8Ua;?rS+8)$exkana`~iDTR7F)H@{y{U<^nd6 zOB7S@26hi_MKM2!JBziau_A5tlvaeESr81Kki*Rmkj*ebQ`~%9>VQ%(K~oiL zr4JJ{EtS{G3L(=GXvc9EE>dD?l>^@o+ncc$(>5i2e2eHC(Joh?NfXc3rQIZ|BHEp# zCo0p@UAx*Oz9Pb3CI-b5W!f(FBew`2NbDl!zo3n6xg`w;XK}IsS6g+$**yo2b^i1M z&+0>7)JAv~=EI}{SFmk(QEPH-2W&rM<`aCsUfY*2?f*S8^d%Y!&x+f3X+u>gRi53Y zrPKG_U6`N>BmS4M=A#!={UOgeky*R7h^iL4Mdgl!R8jG1q9!K1sy$EfIOuhbD5z=G zIWqe-ZK{gVbmR?8nzf?)KeSr4HeO_vb~rzB^_$v61$HqnzJ&o^8~JMmm><4b?`YLD z9-Vuj2>WMb$R2HG+`qJ-VB-&5I?^B9qs2#B%9%Ibt27?^f24guynvN?gCS?^+8gP( z7Xk%px#VN4#GZ{j|FKr3-~h*pPqp<*n_{|=Ai?(;4sX($BH-e6LW1vw$mO4rlv^yW z{v4YQH6mjlIA4vpZJ#y-pOSsroTMEzp10GhpuQcEbN54pMNHV8m=bCArIxHf(#|>n z?z~1^cR*VbC@1rY)%5JKkDZlHa`K`m%FZ1^i9!MPs7Q-yYuh7@>QCI%tkHwLZc38XV>c7$z$|thum5Q=7m;cQ3>7 zN&*T*`MwFbA%0>tSmvW*Sv91MSHv&XSSpl8GHWzksr`yD4r&I@4qtZ==zl)4{Gc{P zQ9g;Bs@1+$)aTx$@qVr-csC(&)%xG#MUStw&Y`EG5Mfz=LwcX;s>S4k`i8VQuRg^- zsBcKqvtk!3U!cCBl*{Va2Ne!!h|2eIN~mz$@SXaKHKE1b#yWekkL>ZwQd%PqMxU{D$;!Psu{TZ#Hb;YQbv~5Pn$Z z0k0u&-;qrLuc3w&$vj{+AxgSNwgtR~ia#jZ0$xL4J#>f*<;4J6CffpD^WtX=1o#Z) zc||Iwz-Oqka5<~Jz-LNN&9it6RV!q*U@_FFeJ9aG@j)H7H=cW3T=R`KDzvt2K^h@n z#jS<~E@EeQMl7M(O+$(-ql$Hdv(?ayE_wv(7Z$|E)Uxk}duA1+DkMuw| zrT;2_Ng51F0hnrT`6t4`-^soA2;9Inx&L?z?iPt5_SF3y9-x{cUU(dCAe!7eYES{t zoB(%TJ;H(Lc(`*910bN8+}~rlki3!WTf-hRbl+{pgEG1ME`xp6YNK zEwsq};?fWj0k!1$>;wwsRhDX2eS?C4S_=Q?mU(1F!|vRAUyYGsGgy?>-RM9M*UFR#U{G9ia9cOm}qmE{X~h{Y^ZC=`wY(&HRzlCsM3k%_ulRwFWh z(4O+Fqd?zB;@uy#uIjED@#7ELhw=X)y}uiw@BOGu8Ba*SCooumjeJCV}hqsX-Pufxvr$Y&BT1<-2=akPZp z|C@GR(q3@x9?D2p2oaI2-?eg@NFxVNYHxWkB|PoY@4MlV?*Xn$9Z3HmPYu8pxS2k& znW{Pfz*^FSld%zE5+G@rFb4&;E}m}o9TZS9v)tyxYp{5xbMe@9kSXOuV!qGCY`4A? zXCdR`^r&`*7M7&^hD{Ee78UcedBW$>cMRLH4s3&ZEbj8;I2t>@S3}25cA{q8N9@9| z`Ct#bFle@brAXZ8f}y~L0rR&5;Q1sBnolhj$?^JvGv{a=_~qKp75n1#>#!@*%c}=e z$Sv1-_4CxXwuu6-ZZt34xYmBy0A~m`inqOb?{3ewNt8ne5ccuT;E*J zZSwIGY{or zDTod_qbkL0+DaT`?;wV@(u2y+VtFgn{A;{;rIqeiPsNMsR(fl-dXxCImEO^Jaz0dE z&55Ampz;z&MRtll?M!>SW`EYYX8z{bFn~Z?k)ki97G9T%hI}s~sro<2JGZsoiyHiF zYke-D=$WQpKwBD<)AUJaG*{iRTdYji1OIhXQ^m=2eZyIuqWl@yJRIL_qvsNgLo+0d zb2IeI3And1&IWGrZgDvC{|0b(qVZ3))%z;-5suvU70E_@at`W+w1)LwfH>c*RKO=*JSB;4`dtgz_ zNZMm!Z>VAG*=8?z$?0X$%h1msQPLn>z!>(71N6k~ow!wrHuGRdh;QS4=~!7!2k$OJ zZwKAu=Y~G`vMnB1@F}wc3ao>8E~CShkOE*UaUb~Z$GEWsr|`+pAH17x5d3r>E^~=* z9P-{iac4K3$ngDc`VA;p&juB35p%M^4=N*KeYT#i7H$wPWb0Wu|yMtHt&@)mV@sgDao~ej8>0(8?@n^Mou!p_@B+#y>eh)O|t9$BO;k&SxJ_9rS zGrjcf>a$D5Exq-dS{=s{;C#m_?0;j^(sfUc<9MBTw>O%$e5p9vTW_zv_OeLsgD)na zoIZNKFKWT0u7)9sS+_*|qmPa^7T5IE2f+e(?A@8I#EpIR7Hw8~S$LV)%&Dp*D zfOGVYxJ~W0bM!3i0xviROk$~c@f=`isW^0wJ{XTZ_BdB>4Nd2ub1|7eB-Wj)w@X=t zOBt}tBttAW(Lpp3cc1+8Ts=L5E4nN>&PhT~qM46s7zW>Bar#{S`U@ZO29lWQu=@%5 zo*+DdCdo8QP%I2<69e>67^HlPt&7EqmHhy0zId*m-UXv-e?Q%9K{P@($At+f4GZ99 zqI-Y6yRt;w(qHe9_GHQ8G&4!=P=w6>I8l!d`uQobslR@w>m(LuqVz~=YtiXEy>n>s z7RZxHa%~Z39(oH3og|Ww;vn_C^DyL~B$ATI_qy~!QX=1{r#K~~CGu5DAEZ@!bmh^9 zv4Tq?sfm31HgFA?=*YK(?gYYRk1nV&vfB7X#d-Q1{Rp}eX9gN>$#CNtowM%CcbiL> ziYe#oS=XL11-s4VOOd~kP(asBER#>ZVQ{+5*XURU1QC1O)2%g)<3XS`=j-!ei~s9o zdb^DJ#0kEq6+)|*sHxFcti1pe$e+v~SX30fEX<4bK=Ly$gU#clh`iY5_=WoVKgn=0 zZeOC**=MtA)px!P=b6IAii}Rd=D&HDoH_p) z;+{+O3v$kyTCg@a%WMNT#nNo-{a3T`**8a`=BATH&&$9Pe-@iA1A}0~xxNMM+C$?+ zcW9dVAfjbr%pjc})h!$ZfpE9jH%QN+B|*aFm}hni?Q;FVpLFMi;<>?ktIJLkfLSr3 z{qLr<?W_e}8Z7MES2_iyZ9bcH^&v48&+`umOj z&kY5yt`{eV>T7TuV%3#k$BV=tS7Lg{I`F)!^ruvqxEvg&Kdzog6Z3~dTKY9jd^TLi z1KDY!&j<*AzotdXM(Dr6s3cA7yjGu20sTkn%{XB2b$T8Jymy@rEozZi`4@e5n?E#Vp!;-^r7neyCe6E(r;5}HL>poy_Gvuv}hg9Ou*hmF;84P2n)^a6yP?C>Eksw z(}%XJ!LC)TQK@sSXANu>jLcK~A#+CA3%l@X3T_c0!&@L2ZhuuB#DKN9);f z1P2!S8%FC(LqAfba*D8_3S%V&s7^9C<_Y>FV#fOqq4NE&paP2mRL_jjd&UtYfadHdM6~grl4E@tFJR^S^+q`F{ab-B>_HkN~Rox9YPm-$j)+#Z?6bxy?7|<1x$W z^KYRN)wk-cyZk3T2Gq2>P4DTWihZm-L65u4QgLjIK1^)CO)u+t20_qb@NCMV^|eJN zV)gBMPqnH>ym`Cc_wv0&B`lv!V-ndze%9rWXa5@w{xR&|MgBk%rx=C#5GG#WryoVk zar!XDS-!eRT2hW_;pr_cDP4E!!PX}i6p`|@Hz_vOrLTv z<^7El_DD33Jof};>5eQ1A17B1!uGH$8)5%oSGPp7u$)~6q{&yz(ZCjM$RLaZ_#?ekcqmx)ORJ)yx`{2_&`~l!;n9;U2hWkf88cPB37) z>ErN@s2M>>5rAzX%7H5jlH6*f<)8B9;=%EHn;UoLBP4Hm)7-Getaym?z!G!aQP7N< z1S`zaz0hD(tt=u?P?MKyf<5N`PdEkC$(u{rg-QJ6>*BlddZ$oy1BXD3yji-SMBa0B zJ(UO*a?zuVMJSMKi?}|hkBf5I1?6$=e0D)~y#Lh=lmklo?Gm%l8lPCivCtWZcX1ui z7?-0VNC$m!!K>^FL0w$_5<8(RCfE@TRq^JR*#$-Mi5J-gHF3qW?1C5hw z5Z_jBU>8KUqPMs@h;5ad*aeZT>^XKpTr1l`E{JN-`v#nJp%>mLP7|Qo%gMrf0)}iM zjg}Je$OJv8?s;2$HbFn{;@1`ex5=@23wq_Vb#ruYHZ*2foB0+r2x{0zSRjT^)JG&y z8NQM>iKi6BBg!Y}X;$gFI5tslf9(%cMWfe={$&-Ov#NkB{O9$KnWRt8t~jw4MiLWo zzagpAGHpGXi}YkCep;J0A&Z!Tii^j8Su0LWg4$)F7(H31o0$(z)?dPB{S>_#d+PJ1 z>eWU)a?toC?YUWJdvJ=#jM^UB=dbz+uUAdeGa%E8k=Vi*OVe1IthoAr1>>@ktLk{etRPI?T*+=E`PPZtZr@Fhw zvI70TP08{q*^5D-z*qbs`>>~SkRrEBFUG@372dLsITnM0wt$MO*@uAvYfbERNiRkR znRFK&;z*1T^3_ToMu|d($i-iCB!&u=x?TD(T*$Xm`Y>c@YiO7BVc5`i(thc~(4kH2 z6Viv_Lpx)8>$pseAPv5#^kEcrfiL_m$6+L?St0BxA7(FxQ$Iu&Ngsw3L3;8C$6;7e zG37_uhoMDPM89Jnh8MN>i1cBIx!|jpJ`A()F;0bHM$IYwo_!c!5!UdJc9$p&*h`)Kb|Dl5g& zyY>6jPtrum?ykBhxJSQ~c01a>f@c|iyhne(RY5w|X&@22e2BABP(%3%P+iYX9X z?$dRpATs%$6hlu158b$aKvWiSzU|PU!!|hIx9bT5^$y%+u*E>YwK6!|@q39}1D3 zxZlEPlcbuCt26zsB3zraQxwhD@sw&hYIk;nZ8FSdrX%$2`OrP=6es5E!&-lpZaM~| zY0fP4FEthG_=E`}x&rsRPS4fbCLE#!0Z%4wDHFMRZ=APzCs+5ws^W02-mZO3Ix-Ys z2R}}C79|7{=v$l+NcJcAlYKR!OP-zsLxhoepv+n^H&0K8Pe|XZ()W3uu4U9xF-3G~ z8I)QmqLhEjyeOjW0$rE!;aGeD#}`uk=!W98YTWCX44hvoj(n?&zp*yQQDCsCtTP=yjmvVd=#rIfb z=MTr?3pl=z;%6-4y4Nn!1HjVmMY)_n;LgcsxCiAkhNns2 zV)$gCGJ@nsZ0q9HyUi^pkclwU~k zs}T>_b}wewK9xRY3HvgZ*mdI>WxHLaxN!xSO1O~s=7#uiEWUu_3n~7ICAxkk(+ioZ zfXpaoJ>(O#&FN!$EJs8V#2=1CVywN`_|rNxh>C|H4m>4NR_UFv z4Rqcru<#$mq*eM~@Ofhu#_2)v-75V8e2mo)BWlD0tFdncX1|(SRR&)MNQvL&pbF6~ z_^nU~5vck*N_J2*e}pq-KcZiaA|8~!!bg~sz4VBlk;X-Uevx-L{fx5mA9+O2%;ZRr zDxQ+2xSp6l@aZ3Dh6(~}bS;GvP!Q}~K&lw?6!X_LdY0IDgOL{6$`ia94$qxg;(Hnw z0ooFRyQzd=z3OE@_J~HoT&_)Gehbwdil+-gqMnI?ILIR)!62l9+~61a2UZ>Wt)_B& zC=;uX4D4MeYhy@^ED#3wQB{rvHdt6SSn=s~J zAnn0y42rGvK-P#eF_i>gdUSW~`WGMnVN!6{X^<69|0o2fu`_*?$tiiLbbG7g?KGCSM@ON~T46N+gSnE?&`_idxn3J`!CMV>%2Dx%l} zbT`9v&5<-UA+o>|059pI6nX+l!EpVGzeS%ferR1Ncmzn`boFr)g5lCNYad$uw~|n9 zDEJ+kk9=VUFJFRZMlo~YA$E!&e%nU@zvbMOlsmfO!|xBi^Qj00kIBqYPE!}hZ8K@w zvocq51g1UCTuPbCznr)8wF3u+29KY1pf`XRPE%oJE{bI?<%lvXa{3ze71P!;~PT3`jCYPPLyxuCZ=WM0TUkZ;Ii;QxucPiRYet5 z4+Our(7;K+%!sVb@>t$Vj;ONomQvo*l0QCp=i9p7q2Nz4bEupXRam);V!27K09vfv z1(dt!wJ)L{zqxj0D0o8VF5)!BR_1UlGYK7Nw3WHuIU%_5m%Q&P*Z#Qhmf&wzlQ~H! z-^xr92}TmrJEQ@$*~xA0qtrQZ^A9i_b!N3h14$sEg!Y(3N0R`K1eMM#+Dju5#s|9* z7|TeMlp=t4Zb9i>bcHP1EOJg@`X_+}O$D38W*TF$AO=klM;2RIXlf!A45}k(25oe5 z4iGUGwiFz8f{VnNkZyuce!NZo3k6T1(SSjABd&Ht5u7?y4^D>0sw6M2W~hx zGtV6aPfUhNsTr-r;{D0AdIWg)AwQsb&uCRE^<51>Fp{o8}-!^T3HA z?kW@jd905z%J(eMFyt|d{L#QZ%3#UKG09n|fjrhn=`V}$fiCU85S+~E{ggms5NN_9 z05PchDCt}hCbj^rKrv4!A-@;K{*(aBpVn}0I?)Rvl3moe?Db(qR#}QTWGLsJt5BP! zk>p@Pu%k4ks+=gwRP+E*EYC?K3t0^e6>%vLhU64is7hKcP??s)pd!0<;ShQShwgw| z#uCYdr~>jJ;0OIdIBuM_0oAW36~%`oa2p6Y!F`? z=K^g|#U#mM@JXa#UR5L|lq*aMwlvy6^hKz_>Wfm&Sw=ZY8Yn=FHKvLrtiYAa=o8FBQojg9EfsY04OK8ZCk%-Mjmfx+F9b|41JBt_sg5FebukgOg6APx5g3Mg;}AgvK^3AFHS zr;>^7`0&&jQWtF8OEMEWK~@SzLjY05VJ;QRD9{qJpHMOQ5L~aKXP~x2LMr2Q-A{Y| z{`L1yKzR7{bciQ42*-#dV>=`V<7r9R!FXDsBp{5QRm^fzTqV&l;;O)uED25ua4MuV z)`k#`W;MryLM~FaB?Ea<(6i(`76Y&3rz&04h7j8YLh3@d&~YRn7#G1opJMeuR4^tP!JxH_jGaq5PP{snR6SuI2>94 z2Fh|Teiq~n2WSur={b@aU?|B*sODxRndRhG2+RTbc}O2}<_4M(u!;n>nFQ9~49qyt zY^%T7@Jv|q#6fh1qVSK?ia&m$KW;D(#qj23QNh+%2e~#wJ`2nKa&Xgg6?&zU>a$A4{4hH!8EAnDG!Cz6ssrI5 zU;r54!)!G1>SPk59sVSwnU{+xOxS>pUIR}CS@p38ll)9lIC}Luk`%;JXH#XTp%4`A}V;jG?sz0nu zq&*woQ|VNfSx?NS8`il29E0wLRd1kmQGnZ$ibsH2Z`hEP5+aaJkl+OP>z%-i^14*m z!qS=0r-ITzy95qMI&F-*$?w8GFU0W3H)xrDvw6m#mEvW8%kh-EyP8T z40n-2Z~P&#kM1`jU4!InfQXSy!dn)mPy)EZ8F0w-&|Y)RR5;dYfS5=Rxh-aA4-T-0 z<}`bQzaR!Mm#fTULrR5;_a>3-OukApxW!jXxzaM8qfvXY#aD|YU!~dnEWXNY6&+`F zI;QnjOd)DkO9Bt`ISThG^oak``=U{LkD-`O?dRJFJ<7=5`<) zX)6_g2Ao<2CxNpu+0z_Ps6--~{~>Y9T1=YjZQOAr=6cRSQ$4a%t|Epl1a#WKVE|D@ zjDtc5A~75^#=ynQ{V<~?%c%p%M4>h^nl^zS0krB1Te!%#t0UR9Iq08+SDqgsol-IH zz53aAr>ahsyc7y9kZV4)ZoI_A7)Auiu~aIsESuG!oPh`%!ve%u3kjIlEHTzeoY3l> zp6HwqBKljM1LkKpAE#qtttWy3gQi^eU?8YjL`ZL_j=8!-9(H!@u|#?6U1X-^PF$#9 z<47IIb1O~i_;ZN-LVbnnYb3|J@Puo%HaInkUSo;%F%vclqHVPtBo1n1e~H#E{O)k=W`nq^1&`6Gq0m`EGKw7~B^ z`<+d)lBl8N2Dk*PAWNR3k8V(!9=9VM=!mq++a@moS|-Jm7{sM?)Fd z8ncT7zd;l|K@Cu1feU0S&MHjtC!AGSqihXjaXMM`3DBGWp#RL3=b&8vfdK3y(<_4U07+!Go zFJ#nG5^Uu`tN_5+V{{_vY(P%GNR&UD;ye%kY)mJc!NikJiy>%MRZ9i}D%1T1+e1r>+k_VjmR)YvizcZg&fZ1sw1Qv7)1vcv3JW^(o zbmlI}%W}~&8yy9d;j$uDXIj(~x*n2{f*)XsIyOdBBT7Kpi1VwVkw}AlK(aHJh?7Ji zRLn@H&cJqS(+-rB1z{K4>$H$cBv1h?aUXhh7VD_v@v1ZAW)-gk7{H*G!zn9X9mw1y z28qz0)O`uoK*g*jmOZI=Z~>D}G380vfjTLmqoRmXgr~$Pi3T5EI^z^SKB@a-!-ykz zR06tKdK#5pG>QamYgCew)`{Uo{DxW&{HTZx#5Eb9NQ3}cRU-^8@W(fl=67aY3H*W) zP?df!)c}lQqVUIad45+e;}pb}>38N@rBNi_ae@Ghw;IS^eU$tR7SnDrGD5h|b2tVW z?MuaF_H&{{$g^>o)^gMX4~QT$V9oP^I9hDF&4Ckr@1Ya zcMJt89ndB5UbdUGFlaIiY7kG00yj-v2x0WXsvPn<>eH}1!N*TOJ^k1;=${8FFUcb+ zM#V6{MQvFj7xx~PKv+01*{D2pQ6H@t@Fuz6EBg&KxX^EOJOC?uc!;oFBTFd7Y!G)a zJ{NcflTdQeD+6e3EBSdKACN1!01bF+8Gs(7MV#L`CyUfP{`fgm-1Q}MPzY0q^LnsA z+Sfp*(4b+%1X?|+_oGy6^$0kz$S{+EB0>To3zeX;>3|v^AD@&&<=`qLoAG3ULDz`7 zkm4FZ5+~PW#FixhCMaN{g+^RROCuEp0wV;s8oY?w22O$jtpq(_y+Hua!yMSabB4aZ zg03(NHL3|{ph3(g9o8U*Z7W+u%}|_VG=gavdJxz~A=TD^O7kt&UI5;47108O|K|Bb zlvwi5#8To3tSHPe9Ob0-mU*$C@;ImSqRn@*J49C)dZHjyH<8y4H)KkA1)QVNW>JVX zi}r~jU+P+-#V_hlJ4TAxU+SAfCEzxRyHyyN!1~02&awU+7-*^_7h+*pDg$P>4fDJc z4nP4|XraCcaFTln57tDQfs|n1g+v!9kS4BRIDQleCni&rJ7!~TiwU}~I-H7t0s?a? zk|)|WEMe>wB<7p&W>1iHzX6>cBq{%!V`w zW~`rKVQt6^up$dOtI?q_^d}b6Z>mNiuJvC@VhPNEA&bQDPCTDWkMaCO5QUNl8QMla zR5F+XDD-UB-zW_@ZB_!V4`?!WVi}W(OGB@O-a|=HAV^WK=}dwt+Af6#Ag1w8*nTQ+zXrt>nX%o{H2ssoZts#JX^)^KvQA@$d&{J zbSSi^A+Y73BbfL0ukXEbXxIFoK%T_o9KI98w6Qt@tSG2ZnFB{dIQ9)FG@nEza)d1* z329K8%nQ~*8D#$ZkX;7T`Ug42TRB5xqf%H8A)fUpt36Nb$ z()A@2R;SQlgxoeesLY}6f@T1nipReI7-k#4cOuPdNC^c2xFNZqAaIdXf*B9Qk`y9- zLsKDS-F(ah=E13kj;xvJ4Qg3 zLXcw5uSCc}#9YVr- zly@KM$iyhS&Nj*_jm4L9JoXuD#FRQae?ct1h~u%TScChc?D%?gy;XjgLS8#jR+mXdhDQh{Ft7ZLU=;|@Hzso8p__=b4+g^DvwhYY2H)hlnNbe*MW?w9Q?Po z=@5XP!>$!uuwd5;=CW2K?~5~~gq>Ll;4#!4AXFGZ9C?4iw_p8pS19O+N9((RoGq^7&EP) zZbbL7DGV3~(m%5AMD3DC{}TM_G}A6Ly(kizUTFm&VI?5YwTM91a^5iIt$(6w+mmno zQr2JsQov~nt;}bPING4~Z5v11+n7#ZS5p6V__6YZ!(qk2HP>U*(e|vY`HbO6YFn$7 zoVUT4#j?Ywjet)3NPNc|InPsgkfPRhEP?w|9>L=!QT8#c|Ue-UJDniDc; zVZ!Z;CyolcDgwm*<2_I&EUFX;gpyfWR`8}Ui9B3O!)7oMwq@;6#IS>~p&*W9U9Q!= zAYK#&;^l^rxB?);9GH&p?1K4CNdz z>x8UgwRbp$j^a?Pq-A>tH#I<)ijg8GX-1;B3tWzldRy-1T~;a$OHQs;G8l}hs2adD zPV^e^z=&tj@!uYM>2KEsKa|7|S%he+;K_e{`EXtBkl^R&DP*d|FYUGxRe)W@SWP)c zNLuDe5P6^Y`={?b`_hU~um-e`69ce5pxlz0S*Ec00;m}glA2lMfNf9h($dKKUsr{K z-^i*#%}67u8C*2RiNYK~)J!ljF&DjYP!cm)qXBFXvm2NsY8GI6H0&e+v&aRynZGZ( zrfR|SWQK&&XorE@$pm~BTco`OSsCakxHd-4WJ!d~rJT9U%1oryh-cFNf{(@mHAVpo zLI!LzkRC96HVGr6tO?}Sn7koQQO2-BVk3sK67Uk0@Z$PU(oKVehh+ER`A$w1vLxm) z6gr+%85|B;liCv~aZncMkO0RkGYkWE45Z*UkQ6?ojv=}tx@W{gR0g{xsHECO)`XcE znhpx}Q(YPpjz5QXD-Z_ePDU_9Osr^tT!ete2SI4QjBGir_ff>R$MkiNd}j2=@%@&H zF$jmaZ%~Xr@I9m$8LfAxFT*MoDjMa|^qfma{+{*gD@8bDjdK)%o-d~(3bK}R>4#Z; zLbE?>S&k@957t5YgVVozuA-$bmdUsd^*Pa8H9Gk@7Zr%K$d84&@|droD3pDzYCMO_ z5^*5rCI|uJoB$2?o;!{9W7r&+aExt{G4wMYxN^h9n$*eAkzwTFGYSK*LGgNefR7E1 zX@yFdM|#3O+pPN=r+X!Y7gyW5j2@`$N|!;>$VC1`mbi@j6}$)IiZjlG4f@4#MhDnJ z|22-&%!xC|gnM*L!`~7{=Fghu=pXSD6c_R+M>OpFh3;$n61H?rv` z3vbQ~nnvgQj^K4tqjSa&6jm<7C?Q426Z>7iJgA`8YxlAxTK&Uv1f6Zf%Tyn%? z&~cJiTNx>$O}vqcpdRr?YXl97H@c=VJ}tJ0oLHukt$dBhi|0mdi#M`KuydMZ@<)|G ze~jq5c%$9L93F*8Kn*>T?qgs{bf(6moTxJZDI5Z(6LxI}xh051(>bv?onnv)^%$?w zwk3l>;szN@QTuDea<4(M<1=1{zXCpKVOAn4!3^QuOmS1}b06D3L$<_^z~_q|Gi^)fK( zfgnXq@C4$``(f0+Baw0PE$U{g5qCKGU&9=kt9aFJK4}AFl6>jeM?QO z5d)G9e@M~*Y$;rp={=m(!{4Tx?paVb)_=4CM{BXufRo;~697k{u0pf%-T@6mkhq&v z7mXK&xyTXT+mJcma?0fO02_b=Uld;^8?7#3AYlAUWtMZv75rPzzc4N4I*Mch*jOXk z3H~kR1Z7Ad`ZfbR??m{l1wtMp4-Pq_EJ3HnrudycIC+)9pNset0pAJIsNIm+c+~!$$r46J zTb_&uwzVY;Ytm)Z)`}TzjZT9Z=yJ@Uz*Z%#&+)CI^*I5~k)?9-<^FNX`2yBemfQj1 zp4s{lT##vx<;s}c5#{Lxl08&1?QHy)#^TF49>RN#7}L&{OGrMq`mc!NA)n)@DdN%m ztf4%))V4Faq%%_>q0UMz1v{h-wC9mMq`i?Nr4U;qA*GP~_C~v#WN)EuL}#`XLb?Z< zsfcteDI~u^3W*|;uwo}BiNZ>ZrJHOiPyTB!0hQa zQrfcYP#}j<*peOcZP{UrpJj(R_{izn9v_65TJf|WKpzl$5Pby$RR9V{ouzTI$z^!J z2PnC;<8{}?MK4RkaGdqVW?E^;k`3T_=nGRh5#3?e3 zL{~G@$;U-$QuruXv(Xkl3N0rPkryzsvbn@cnJtPUAdJ9H)hvqTD30a$AOPW$p)N%Z zi&V-v7mm}^io}jUZEYmGqk*Tm<3;DrMu%aC(&=~s)^POS_jNiv*mus~8X%25c4FBm z>T=i-V8Mr_9JZl2A>hJ+4p0I*1)p@<-2{dXh*h19i&``iE08)7%a!WRMp~v9Rs#?& zc>4&;Ivz-{g@)WwBU*JajCNEimP*)?00g*lXCkdLv4Bbh_PpZ8E=Fc=nPe1f3hX3U zsFKkER%cMwgw^R;2|zij@_PqoV!4_q%mTfY3pR!-ySito&VlMc@ayC`)?Oodk({?D zsCBd>kKL?mY1cuV?qX!5%33uTD55SuEXi?QL!#*36~jJJT-Vj;hM93*SEE&&hc-Yw z;<2uVmMu3!{4VVJ@JS8=kfkkNSmX4qwUsd-*B>Xo>uR*2SynUJUmfR9m_fG^zTKbC16*~Gwy?NHi_RmcznZ&A_WoX|qlfNWBgL;41;c%ZDsIFSa%=U;=YO$wF+D!IT1a!vwjDvO7&jmIp;(`}100m6D+Z z7||e#9wQX~$wnGI=PQe%*EA@Nct6Kzjjkk>5{+*v0!rXH_7yFt0};aA-T2ET7KUO_ zp#+S-xls5>oDi{E3S*e!cuL4T0~?olui(AccpAv@Vtsex4qC!`_?Qh0>dNt0Jx)xM zeIm_P9eNlS^gWc0R$&k^D?5}<%+g~U@zB_!{FKW_KQzuL=kgv#W(v43cO@oXg(OHy zEMD$mv{OD1`+7hj^TC>)^eZ~|G)7`}eW0h&8(gBKr_r__rg9H&UeG=X3Jx=5*h|6; z;9;#V@nl5QldypA2`Mb}GP3BV4-e^gne8JAr)a=6A&JpF1_#A}UYG@I#i(9J+bd-? zwuof4hPHzlV&o~ZiZ7<(xnL5~5CI{D3x$3e`W0?kc`urQM0GEgtrB`e*Tm%)AqQy$ zkqf$0{6aOv%^-ybwGY?nMw_l^JKL~P z-y;@kQxdi~6mu=Lf)uj{#h2%BfBbTe@txn}B%i{5wXmMGc{3E)r)osS_-c3^UO(^Z)Z5O?G@%H`{{%Lm~7(baP2MOu7E&ZsyZ3Ou_cnBghpe4*%nBPIX{1mLr0C zpXE45;xWaE&Yz>s7HI>Gg=*;*v3{Vj4$8g@O=AF5`?F0}?XNQ-HP(vfP0ZEUhBu8A z}2R3*C9$5GS8xLE zqor3ENoV%alUHyb?Yp8;A6eRsrhQ~}Lz6zbf;;@|KC-y0)vdO+z+#S;j=}0OiPk1v z7E*Voixcy7zYtd%U9q3{%9VyT>g9CE%=RAM0KaPk_S|UmP37afm)bjce#c98jN_$- z&>~7qJAI8e_2?BFZ0ZfT%IK82JDuz-U9^!$qPdIq0jYGC?`1LfDnm<$A1q(4ql%O4 z(?gZ2c=kG@Rpf)KjK3-EqHF_iPZ#A5n#C}|(-xR7DvE{~Lo(RZ5vnDuXFxE;jZ7Vd zbGQ+Z@g!C7v`T66DGlry#em_4pPv05JKRX6?|s9K4(VJTI-nu>U@P@Ah^17O!;KXB z9vW_3kXFq$gpjA3!=x8u&N3Mk{YMz*;w99nBS13MV!;UGI(+txFwV!P^)<#&d~UtQ z7}7!=s1C$(wZZ;Q6)#+43`iM?#Yuuq&X(Dyc;H&2gBgIdLZ;wOn8?{SdRW*(sD=@H zLf-7zY$A#Q4y$sqy)z+O$#b@JVZ_j6hv<5((VGr--E^&ynabxD8VeOzPsWS)t~G+R zchGXA(ZiW}b|=uv36m$f;O4&=xoAuDFGh8UPYQs80L9Y)CO-GU`cWPi06>s8+2oz2 z2@)y!Xn`$_@!0{&-Dva_B{v%WD{RX3!#I;h3q{-cP{x^;7SbZcYsFI* zzY~HH4Kjbch~8*)4&kUoBf#xLE+pB(B$<)|ZV*VLDzN@%$q$EA1>SRezPUjYWa zu(YRPiCpsR1wn}zJnTjy8I%u*B61@k8P?wT#UV2sSi!oMloAvv&$VEchvgz-=$r`s z4S?-EpN2s&s1Rpd8Y22R2g4GKG)tuX!h#g1E-X)@6EKqS8l8Y?i4dMHhD+)gmE{z^ zn~hZ1fjeoTPiI~%{J8R990Y(C(25vQIQT-Vm?j5bPFn|Guo~vJ5@kXKVbY?Sj;1%9 zeIcb??AQyFHj}AbNaO|E%5yI^-ovOI$2#cv3mt_jCkR!nzgcM@PrX3Twg833lX^xT zctMDL;057);Kgc+Jof_iRxZf#PtUz5`Lee_$T;#sQ~w+^#A}~;L0?>mBN9yyz2Kw^ zUy=a8=$K2=|8UGj6x?EDUW0^EOt-ab=y}xyQvZ{aEFcp)$>Oq4vM~D+r*1JaG=%Xv zHa~2nQ6dbYrM0g$l5uvA*{UN_dxPOsi3FM+i;9ZVHyLvp`id+NsjtMcn~kHiM11fT zV<_>vid&2aFa1z~;g&j=ZmGafff9_^2U9EkV2HaLjh*YUc#(ZT1D?-KlHtDSKGWF!q2{}&lH*On4E*ltY4sJ9KC5kWpYTPdV zImQ@8J=ArqaU=Cu?pR}<3$uw+ynUCagXnszF;dpmQKZN%x5I!Z8KvPC31UMajmV?pjDIu=a}&8tywfNY1MV<%G4n3t zL@WbG-Z#N0485*m8d2r~-;D@{j-+xg$a6~e1-gJ`9aDRyGr|gqTD1q)Y`NM+(XogV9$Ei^q zIm13uaAJnUJtR~HcsZW)4AYS%N_rAk;K{I8|De-K&=N|14-`6as?~ury96f9yM6~` zn`=sNMWt+b2b@`Q$WzunI=7^fPLXrRss^f2v0p_5Dn?VG9>!(&vu5m0eCyBAXrD@> zJBKZla)ap#eOy;J(F|F*T+tMl=UBK*XpBofm~5{HLb^h&^9U z3@^@C(h$NZsLm>5?@U96N zAE4aGMB8NcDl7q4iy(0Hixak>)-sbPlfv)yig{JCm8P(io>E;fnx7aFN; zH&IdyEsM55eSVyUrGeyo{P{&jcZR-azEQ0FB0kGE+W#puk;KKuY6Xvp7A-MOH2a*6 zPcpQsx$hORWvO8h3O-zFJbhN~c(g^VTxPsSDaJlz%z}vj$wS5gAUG0PZr~hub!6WP z!&KDI-J<6-v_fq3sxBU?h%q>A{)ZD1rVe$2SyOf;+J@?vr5F=IYT zxNEI(Q{zgTye-6)M%Nmf{$+}IYR39?#ud~Nhu0Ye|2Aa@@%-aPKt1Xb_3Mlwk&aJ5 zRp$MEUT&J%8P8Ni2Cg>>lrtXyb(m*95auvrSxy$g?2ewsNZDvyd}dqS)@vFWBDB%y z9(s*gmn+KyT4^{jOiXN0jGJSX{MLt zLBOL`PaMkgt0VY^FRU`dbEosB_@#5FUyivHS6fkoEkXz1vj>{<%gg{KAIMED7 zARV~V1S_}^nKQA?h8?Cz%|;_#O=Y%JB&Ssje$|9#f3s-*BnBJ4{hu_xASJ{zi#_c` z-z~;$@?5b5p7*yH_ryVo0d_001||j~lefay%l9Nqi){vgTk+nGtbb$UrD?XLb5`82{<(F0^?S6)xmdf5c5(SGi)rf3APhqkq#h86q&HTkE88Q|_MZpL!26pW8Qb zG_~9Kl*r9Sw@sHs22JT^w2s`J*X_%D#0|f9s}=)KcFT0-Oqw!N+<&rLNW`D&Rv6iG zs#~oRS#i4CM~WwB((RKRQ|^h(QL=ZaqNgi+N94FG`*fRr_ub)`JZ|#nDN|>Tzxxiy ztUDZ&rcRx5=hzvyjX$?<&ZN7h+Fj-CqFsU1NKHw$H$!~)R(7_?tjO*aSy7SwrV<(V zPIfa_B=^1S#ZDJh5&8Rv*$33f#*ed?I3rhmmOb4QIS|c$RZZ*Jy;r~PJ#%g!cTe|T zeS7!s*1K2#KK<^vHS+ku?B_BgGf!tpelr!5K$!(nzM6Px@X?Lnx&&UsXIVJ7f zmyWyj?mNZUWjU=v+U?`+7<>1mS-OANv{`pezUzUpv+kNYWu|}X9d~5=XO6vN+$^Gv z1V8?+88>O%*qP%7jh#7*ybXU=#&P~Trq1w#n(&!CcFJwzV)^g5qj3S(qEtI`h#mjF zgeDMNJ9+G+Np=bJZIXW`$KHC^l(94JKLdoEsdr4CboUCtk)l%)gOWQ61(d>~K2F z-`L@DnClK8>c;q=s=1t_YidxW!|~T&qAKOyS|3%tj)4xxbOb<}bA10}wVH_UK_pDZ zcO=4F;+y)r{N4$F3j6>q!5QaqCAz@~qT;nLa)yT%eN(Nv5G8)DR^#wJ()}Pn%C9Ea z0Lg0GQDi%|+m15Z@rLcFv>p3xM;$p*_g)g^I#v#Zj#~YdjA>=Z?4$syK5E6Jpb~~Oe8`H~P7ZHebFUq<$BsE+#UwZg z$ta}oYt9pLm~W8F8|U+KMR91Ji~@q{5Yr+(t42*jCXWR_Qj}5zfwGrV^hAm_oI*AO zDNfocioc=KJzm)i#8glK<^7QyAw)H_WA(RIR5>}ko>)7gcFeNFGNu8^+bMvGtKyhm zRz(OnVaIGff+WsfsK=})r?*$SVz)I^aMa4biyYqGF+lg*G5Oyi#@!qF6CGwTd8odR z$r0bo;h>@6L37B@#6;cS0;GG)O1Xg?@rbfgmfI0Wk1Y$OCAz#mDtKAFmHY*AxLP?V zu*wcxaGU}$h`bJSGr0+b56BVU++p`=y&duR_msltFux&3Jeo^Y;~nJuAK-5cWT==z zsIZ+f$^sK<_u4VxACbhZ08CU~L>@}Nha6r7wbOV3ZjZ&j_KqO3C3(1_W+Ix5Cik07?E1M<;YF z1#n$$uB+j?QqU4B^}1gud!y95D1cKRo>9%jo#OS_sp}|`Y7MPELHSZ*)$XJKii%n> zsdlFDuU5=u_rh-6|fLAR&3#KR^B(r;Y>w+X2I{oo03z3UP?*- zuK^wq%JuIhN9t8TE9k`0254=R>ZF~j=p>~&(j%&ZOpyw6L#(U{ilnyuNRH$-ApAzL zt4}RU`zuG6!sbht& zHm7yy4f0T)Iu89E!1|CUqbaZj;fG|ZUF1m4XbS9pJ2rnFV!atLSc@ruO5ZDEVzB-w zW3B*2&*vfmEYU6X3FgXj3Z#s+G1UonbQtP?42ZObaF+Omg*h%(?|glAH+yGy-K81ya5!Ia(|LC^Tx?#z4tm zXr$ES>9Hm#?g6;t>{v6c(bg2L5nNxn3FQbLVi3%k0n-~3Uc6Gh6D#f>+I0g zOR1!epl7Qac2WRihhst=F?wi?D7ZipCX@mzw45AX4Uk)vAf8TYxN)GT_0GUNaTYLJzooB}Ds5psCD zBO%3ro|dh#VnSu)a(72Y2((ppaGpS@+8vCwl3dQdo#0$oNP+#(ol$Znwg&*jDEkor zJ0GQV{eT)X{1~Te4nU;~VTEfE=Iw`>mF5_vFQWilwF=rGS91Rb5@i7M)^RjgI61ui zQ3a6_4Fx;qM{=b4CP+@x-y6?OCt60Tb&p&5E69QTK0AM%9kcog#Dox)2CxoBxt;Pbw;rMyF^mjfd%Ik~IG2hWTqqwbHcYKa=k|^CqnQr^UYNnvl zQ0Ho1h#b68M%=!;npZCCk&#v~qmhxm%~2sOSPr8?`X&sMfQ&>uVQN^Z{BG@7&Fp_S zD#$>%IZ7^UrnQ#7hrLmEQFNylO zn`FKRkdM-h!Z!=wt!Xv5nJEPRixv#q+y&)xtJ%~2=z2DEw zQT_aW-#>nNy{`8&Gw<`9IWx~Z^UR#ZwJT_0oZpt3qMB~%PSx~#r>VXfonJNKbM!5Z z?{63v7lr$EQx^(XC+zB>x~?~Dher2ivEpCpqZW~0Z%URH8;5dMqyWxCW3-`SCYxvj zYRnVl#_EU)DtxJGIDUk(fgyKP1+&9J)A))2X&aZes1r^>Q}fC2B4{^;4zwr={sE&ChIFJp^a&%Hm2LUg* z`E}DT^;5&z1wM~kjf!)$eGfkZTQF_M+{#6^Lszf~r<7Ah@^*qspGFJOXwL3YUGoKu zidX1HKF9O#$Y)n=_)Jx#)L3<*XGh)kipbBsDA`_`<^7aD*zZsm_zgT_Nt?^{v_=7Q z&2P!V9o0;g1psLVxymSC@$NI_b8dlG0r{;is&n~b+lW5s6fTzh9Y9`u9DEDy_fH`6 z|G-FOe)Zp#zK-LScOC(RK1{{&ZhLhQzTcrjpeDE|y6=4Y;>rOzQjeknbY5pL0N5xU z&};0iV?dh8E+9u>LSI$k9;hfQcoP@E;|`+L*=Q!rfX5}kt_#{apf%yd*nJmahb&lY zsMfuw(_Tl_i4P#3tz8p}*;~7MD7*S$vC2Q=diJbFOEV%8)2BywtWHE2jy(=5CvdMW z+A2bEn=@JjOuDfmV8xOkLOIOIB9ulPB|;hK5dnK#f%~Wju|tRmWf6IZfSG)&DH3iC zM2dj8;;0DN6^Ij|G9oStxqNU9{9}CP42ohFBSQIOJhG8l9thDRM5ut%?Pm_o5^#V5 zV+9eQ()}xQP?JLO2PyfWOa$z)tcrHEO|NmyRJ(=&hf$uRy*?45rch>Z8*w{@d=jas zn2{Xh#|nW942zj=<%As3$3|O1tR*B^!v3S=c-YE1pHM0?2U-L1n}y$O{Bn9^_rO`5 zsmEN$Uest~k3H_n`Lf2hX8Z}TmuIOB%8DelXF6YF@f#}LAyMI$Yq!J(>!Vzp?sbKE zP)?s%8s)^kC?_67Ic@c~s|pu^$8l8p?^KbpBEtPn#`^3J~Au^bH)(QJNiTVk?vr=U=~N%3xRt0tdx3C?dAP35b8; z01oSKQBLfr)4?d`=xl-t5Is>&JdEQxiW5;zv}vrR^QYl>j{2;q0I|SzQwdL@fMIJI zh{Q1<5ZB`b9NybePV9qnq7M`k_d+3uduNmr4V@l`a{9!cIG$J%<;3+kz6@|b%879v z*IjcnYLv03opx=>sPTFA_*j^O?0lgVLq`2si1lCw2_8!@md?10*EQ;9J9-8gyR*4Q zzOK>O9H0+)zf@whU2@oM*}NZvLVK2EJC{**On1bL*2%J=-=>2??<#IdXGvB#wT;3e zU#q?O;Pwg&c2&50w!+~V+*e1i1&}+?6m`CTYLRcye;HP8>cW-0*V%S?A z4wQHU(bcgHP=Lxys*+DU9jm;F%Oo=z`%I z2V7HxCtA@$jSmnpkbknWD!<=RVJ$Q@S0sy30pfA!Auhvl#C|$GOygsnU*lS`DTKea zssqbA)d7Q0V;-3PK&AgdY{c|Hv<$HZu7HuledH5Iv{nH_a!VEVPSh)o+~{)#1_RL7 z#BM-FE}keSb{vTagTguVDY2C%wCt_&tD~k2&OX5b#3SGl^P-}}EGVaAyM&6+fu(Ca ziz{V11Lefq$fpB4uCXBUneJ>tpre`w6vu=EiE}jW()o=vwn07})pm{7k^_z+4(*kYCv53>b0&WAP5=F0QP(^KY}!Emgv=E`H7NYl&Yg{MzC7DSqAY z>w#Zy{QBx&Kj0wzM&g$bgV%rLZE=UxTi7+t)A+7f*d?54G3Fbay5oyGibE!hpXTEl zlEv`jx%ubXmc?jj#wLK8<71V@S@?-$jQTfY)nzhxM*e|uR5FIBG&5qafWhfHRRm1V zL06fBjg_q;d<>2VjldD1F*u3fboXci5+#oTAc-&tBoPLKbd5zrz!706I3kP!hr*Q6 zx*Ajbac_5s+{bp!@G=J1e{!8iqEZ1jAl$Q01aZKCK~u*0RB4>k@wH>@sBwd*GWG=hEdU!yg_3}jTrC4%pq3$y%!89%N(a1Cq4J`@#@a!0n8Yl zNFT?&1!75Gg_ge?gD{-_ZE(d~f|jEki^0Qux z?|3z<#Ju?LEMv_sK8@7fSZfw}Kf7qBkIBH4Mj4Jp5*x>+XN~Eo0Mli$`9ZX1izR3T zrgvhtU}ITM+?oumS)()>gXQP2Y$WChSJZtB0ho=oDOrAV!h`)m+DpzRKuJbA)otHOiEe<|s*xFC%5_erQ0 zg{~6W48tDuS5${=Mr$uK;W66sVJ_M&|8~E@F2ZCr&?(13W{*U_%hdUt zTMA9NE#r{)%q$LNE5GOm`IOC?IDiXu&Ir9Bv->OK_l?e{9R7hE2bre8{0zt(qx4Sy z%Kx62`Bo(ioXp2xos0QeHgT|rZI`|RR>G2b0!!urU2rf*FdW%EZ%IDSh^EZ`JCIWFlHXOi8Y=q2aXC?OQe98$Q$WI`%GR)66Rka)|`mg-& ziJ5Ozf)`vDe4fi-jQBo*f-Wea()^GoLZ)4mhCD;dys`ku)|G`o=CsRzB~){KActuV z^CLcxqao8JF+U!%X(dvSVDqxz$p;76rm2%LKOba^QxY;yTnCkNXxSUGWyqAR$~6YB z0ysQZ1^gO9CJ&1$)8>Z+l`@p-2$@$#x!(u!Sjaq>`2mo5;z}RL^&neHxr`13hdL>T zd?1JEW6Pp!BV;?*2uy6%B!*G{${z1e#*|u)(r8GL5En4fO(OEL> zELP|9*jV#@!o!yE{(%4Xv2_5I{wt$$x|_Hb{a60?1kAViJh2=4Y1A}EOEzhZ87SZt z((-dpSAD}V{;v!Nf_!qguKZWVm_|OET8`JpQnu`ga+448E!$##%jvhx_Xpch2{s7} zx_qFtA7tk7HxaVM2>_pVzq(%-g00Q?UFN9_4zT0&5!&IuI(yFeSQ zoJa~e9DVyYayZI1#lBd`8)Q88aJ?yDlyKcGV8r(*S93-=1hVgtpOd}CbK7fTzf5wt z3b1l^NlxAma$=a1hn`7uY!hwHq<4#46$%-P>>Fpfeko*3x9^`FRlTrL)Wd!wFsfA% z3Yqg4EJW?t(r!ygTj;9gZHzJ-VBb?5 z2JRNIDqFg!h;HE{m2Z`Y;ekC4p`8y@)vR&{c6?b?i)ZD}=&9mtEB}9w)8(~ouMjuW zva5Di5uT;s|2nX$t3z?)bKkT@`ie3vA#kzI39*DHBEZl>mbem%8?{Y0-X+PEpRLC~ zo|S*FnKvxp5@utF7Gf#9r;ZF#mW;j6RAE$r(xo3VcKyrP#R6{FCjN(!5%ifFVo;L7 z5-+Z(M&q2zK2+ql;63Xo3%uz1p)B=3EUWI&6|~%yRKgh3CNPxjufWE2gfWpv-l9YX z|5{){$4uPj#(aifD-1w6gc+@|GrIz%7Yj!%E@>Re;Tm1ZaCq2U3o9Av_V}M&0hNt0 z_Jj!6!^-%);;QXndSI`2KLsxy57Ua3TnGu4uxf{^zK_wi(8itQ<8g^yB7hRT)3waU z@HL+>!>cJ2G(`n=k%r1|6#Gv|=NEw+$0A@0JZKL& zAa4}`MUf(SLbC{YQ5Gi>6eaF)b*^H(wI@dY*qQJ2B<+jpQq8F8RWSS*)JU`WqoUZO zk2@B%yrvQBWsf-L>R;ceoHgwn7{{U();Hc{aqVhs#CUN7{u;g_WGwA^8v9EeIo7^X zsjD0@&fpt3rY75tqny7h*m7gP?$tYBdp}d&p;EN=27Exl8Gj?{i>5}1{i6&w6iDO4 zI>M4&Z<-l?jk+vT>!EDe?vpSJw=IbOV1-BgSg%5JKh-+r@nrPOE!T8EBgP(*;%e$N z_P2Ha1?95&e+NP>R)V_vw3=e=Zxin3!<7fH;#Ek z*;^WMUPWIZC(mHL54b5onj!4vV%J~oj0VGAqEM~|4m;!(64K(F*Z5QuGo;jjSAL&B z$;J$n(6dEYLNtZ^H2o}JY1awNgIOkHan!8#MqSSWzj>)v3B_I{Tcv%Z>vSjMylLfE za;P1+*VvJx?=2cYMb5ZcON!!a2gtCxE$R#9Ev*B8L7Ij)8^jtP64}2$rm59>xW)jD zpW>DiE+A&MiKFIWF9%JC--W5FomWC9+kIj!Fn)dVn&&Cj~bKeA?7qb@S#HrvD zd+GeeI{z7tV}4I;HS^*IYRr|}wdPYJuiZVzwe3@*q|dHMb#2=pEB;ob*}vaZRJ(+T zcwvr_fv!iN8m75_E-LTE&3qs95EIgWj8ALh9@adTvO#Si?bwl>MFZHsfVJ>iU7@$2ATsOMd0)xRCEE6h-` z5pIYR>tbV`IJe6!v9AP_)6RAcSLqgTAxxJBAK1;dqP8k{GhJb;ehPzNSTwX(PZW0W zSJO16`i3op2Wf*)`^LVCA{`pL`N&KU~!dE)|vrgNFsQgWR6b|XE zuw*TTHV?kelT}{Wxub_yv)5{P4Z&j-$tliZF6B%r%+cgvxJ+2zA z8tyVO-&603zU_WXrtU}`{QrP!;Z*(*#}Rwusb!*pE#-uaUAo%!V}lT031iW zj!=pC621y(+Pv`0CNsKVznEAB)=#X5NstTtNjL#i4^M0BkQ^|hh}JryAsC*T3ua0SHeT0tGHzylSe zGt7?`BksTz6aUut=Cb1iOkaPa&=1EkT@@`sEL#crIKQopCU!vuSkP0aivYRs-Hr+p zA3!m28v2&lP3Nyi#h9+$PT^*Z38u@y7KrEcadUATmnhjTs|RF;K)=cLMIl@v@mFLJ zbE9U&_AnZvOXtti=#4Jn8oeQ|gt!&?M1PIGU#jv!s37xa0(q0M4vr&cLxqX+p5bN% zcZ_P|z(T+^&(tG4SwLiZC(_*RYK=6pBKnw5Ibd}6^8C0@)7-gQj;i0FVu$w4`wsm4 zlWt`?m2TInbylNCi*n@~kMR0zWS2&HveX?`qu=PfwFmY7XmH`7mHmd4^!9C1*6~Hv zo(%^S>R80A!0o)z%!LJ5>P4H`rUpM@E;Ky5&gYX-Q-!S|};x`(<>WFLhLE$0UaEU5E z#AxhcPu(9iaHw(Ap7ZEo6b<6JT;oO?-mVrSj0XAdyjByyXATYl=l&zE??xDo($BHL zr(-S|K~X)jej01ktXmZ32Q?vQaX@+Hr}5}pZ{_?)R8oFr&L3)&aud}Vdp0W1I3vk3*U?Kj zhM|4jrKt3YMqLm4sw+`dCmRJlKH8PYT2;om5!WXqMs=KmTG<2tbPbTuS>X<(IYew8o>}Z!QQPQbsDEL1Ey2aQc1}0Gv4@Rv z)tF%4!x%)fH)mzIj~M**ZSh-9I?E9q$4}-nK7Mpva03l zc!gdbcD#w1olEJ2zo2|OLKAiWdg_#6j>_Nq4VvQPTJ)u{&c5-ktNK^Qg%;MC|MyJR z8LTr}HJgvU9iEwyJEk%8`8}84*G8N@>_JrCZ;TW)@Z+fTnMN@Wd+gJwyrz-Go;&^p zFBnm5@XIBx(zA@oo*}Q6xR%c{?zq;?HcGp`oNZKcJ(_J4cU_%r^zd?w95#8FtI`~! zTG>xv6@TO4Ls@to6DJRwHfqAuDUNA_#!elkXrtyB0lDO!1#Qb%=jup-h=R%74g6zId*39Y~LKIK~e8 za>7)9*RHunrQ+`opE@2dCHwI8^D63K*X6m!h{DnDc#SkY5fJ|+yjv30b)K=@qh!FG z5N-brF=pQ(gi~aQR1cdW zLEkYi2R1%dQSz*TRkm}hh{-RYWxt5S&S7Z~E8=VW3aF%*gb; zlLafL9B&KN!H~V~IpfAaKd~vb`|IciOQV`hylRdFFoQN^?fcz#hvgNk3e1 ze2LfRRdGg1Zh9DZzQplMIOn1$GuU|LVUJnrnz7i3x363t)qaUF$!=e;D(cWu;~S4+ zL2IEfZSBj=CFW^tV?EjwHP(mWm=2gDVmN&vK@TfIbf1>l(em=#k%gt_hF-AVzWq?Q{LU z!KiGH-4~Uy!N`}#9)H1=bGuQdZ1^SWM5DSBD9nSmxdOp!8wLq|-4$2+?MAZ!p;wV9 z9v1n0xos;mnsVV)=B9EebZJYmxx^t&xiuntMt792!x>q!bu%6z^AjpLp8ddN*X`}b zXIc3?MpfUaE<2339@&u?K5Fc+My@A2jgqd>yNo=!8~4Z83-kvJTwm`p`j|dbM~(L% z;9rF|n(-t@3%tZXV5;189yxZvR39Id%2y4nvQgRdIs5_)c?6_ye|-L+N)=K1pW|!Q zZYT%IHxfo!srM?F!7ooVaQi-4C4bkX-9}-bI5(PxvrQs}+}uC1{@}=@ z5R>feWY><}hSN7LnQW}Ml0?8PlqLe&I8y}7sKK|$!AK9g$5kZDfei)rXDV zjykZ%_{GB>b~kE#q~YgPD)lM(s6o0V1U%C@!OvW04;YP$r7=TxSwPFQN>@FPD*dbB z@8P-XWr%CVL8D&2gqP&4fg!+hQjmN7piv|Ds#jEp-NNu!A+CbaM!9bB%#j*__e6@J zI3R<$G&SUgN`esq5=WWfk~vKT_>c@KmiY`<{5r%nKia5jX1oS3Aa6xHrO2Xnh{B2U zu)d(CU~EAUy)Y#bPa_f|R>Y%s#GI#8IvW-`Oefk@enD(mFuhvyQ*{1QtUs9VWhyi; zV^}cbyHjdUBMPfZhFEUIjKoHW1c+~&sPYBFRC&pFD!m>RXZb_S;cSPm1J#yB3Ra#> zk3|4Otb@BG#II0cVv(nUrY+xAm9e>%!paCWNbuLV51Tj~pVPZ2tgpxG;)8137MZH> zHg-$N3q*?%i=jfq1z2Sgt7zUQcwmO<==>~4{2%>j2-dmON(q9o8 zp{YnbfD;olJQY^QI)drxTEPP}G1Iejy3K6G`x?((F~2cROb@qzn+od2>hvZ&@WuS; zNShQ&qo%~(nozrwI&h*Uu0};zei?6?5I3QT86Dojb`&uOjFGq&6(F9*qeaAW2#|?| zu^&R5+*)BrxMik4PQ&_x!ZIvM8D`p05n?736CY!rpI9CHzr>|5He#`^3Ue+~_(<=I zZN__A3{T_GGQaij@o_H$l+-Z z3UWoCFw)J0g-hW+;79g8+4 zTuL!ZO0FIV3O7MEb7e`L))sNgZYjvOIU&{NJVx1TBo_}t0CNq&W z;8ggxi%^?qQlvw~*)A3>>_4N`5Y%azq=x?Z%RV<|yzeEIx*$vW(+lzK8m6-48&czo z(_;!Dd_6Adjenfnex@F#yNfQ@@3BVd{Ldx(eK?Ai5TJq@urCB*&(J;%o5NrH{?u_H_rPAa_}1Fw@oboIZWglwTeLgnX;GPjG5j@ z9F#)#MwnHx8Owm-ML76W79pD(r-xi;dj zOs8A2ilkf`GVPc07N?Rq7)l|Zvl`{1P1KArvi_6VR_xKG;F+no-`}NXeWAD>hf}OHwX{6VqE!9@0+99B4@m)CLsgk*(EU z5#@q@BAXbA*y`x0UWuXHy|LN{qTH#4+Vi12sHu`U%b0D{8!wdG-~@Ckl&|6fD6`_5 zaRP4ZQ2wgDdZUH%*pHP=-@cm9@MFUErhTi)abTbnJW31y!`%6J1bM%U|IFD6>mK&;`}BoP;i@ zu4L0z1}CVY3+mtml-Y0F&;^E;U*igVwfregOqpABXVIiJwY&%yP)o~YaRHRswZ+k* zwYBU5zmArFMGMtsNJP>_bU|Gp`@amXfcGaUkHRRZujN2=0cG07m*@iC;Ga= zRnY~MX(JPH0eq~V@_n>WBP~})7jRx+{#6rwzyyuw6i&d6J<3CI1$_R2@&L3DWg68K zw9qG7UWS%vrsZrn0c9H416+WgmVZSTIJMjWUC><1RnP^LO zE1*o{T!SuXrR7Jsg4S9tiVL7jLp_2nXrtw5v`||uk46_zcHmbNUC>U;6WZbhv-UbM z4_(kf%a?EfWm$Mwv^*Ub z&{bsg{};G|Zn~fmu7EO!$Qg7&cP*bp7xd8b4Rirzj+}qc1wFOg7hTXx%K_*D${a=I z&;_4qIT~HiTg$W21%2p|NIKcvHSMC&(tdlpEBd0b*z_!WOZxS5FoWd?+6o!^oIJ<_zPKLt&eP2SqM`7Bm7bbdDP?O7lUy#5n zcnFuX;6#Hfs`6i|E9|4w){7O^`x5{A9){R#D6#nAuvixk!i6xItB z*85l13l-K26xItB@*)KkTkla=?@w6oQ+W1rMI;yp?4iH7MqD-~7Ym8RM9givFbZBA zG>F_{BVA7~8_D*VeNhQljP6 z5fCK>9z)KNELmKuZyIHydL(h@I?Zq`zGahL5so8565)!?`BsE;2m#~B zxo&fw65#^kCK2Lo&c)|gbP<7}2r>Am;kl*xk(GdOO0p7d&h_V`7W|3!@rZXFb{lJr zi#!IqYr!Hcz-FQd2rt7$z_!^g5fEA*z37^sY&^}Gz+=!qM-!rE-!jrXyb_Udz%?bs zxL;x7)WHt!9{W4SO&B_?5w?hj8e<2IA7NOZdh9e|Xw>Py48zl&?v8quYV^&LEB*l$ zq8|g&T>T#!mCU1Q$f)j~nqp7+;Fk(H4ZkP&rQ?@@UnYLGY4|x)9^#lR+(3e!N04)8 zL4H2`N=kXa6Xf9=Vd@XHk7P#v52M3=lej8#rkT%C!urfg*TP~7jXXR)WRC@#!N-Sr zdyvO4?WN5vab`TKm%u7IkG_D09DeHTHiW59ULqr(wc%wURx7WT;(K^}FFfoO&(3zX zgg8q`w1gB9Kz?H7WLiQ{hCV#h5&~W`2iLXV5)%K`oD@sQfMDWINQWR5YF(VK!l@@f z&KYx%?*P^Wat7_bK!sl6I-LaMgp~>8q*p*=aqyTPfi!2^BS6lm4Utbhk@`F-V=@)oNiQMIVD%rkU3xXNuYB2)Wo)BNeI@ahkd(R9b^5VU)69>>xg9JYd{Ti& zcE;kFlf!d=wGA-~+Y;2Afj5!ZpRA;ms&B^ z9)aIP{OaPDQ6beHjb8wME%D2aUtIZAdkB6#hy(wB=`jCKCHv;6najfX$?AJIc-ZFt zyk)ROJbCz51Z?z%%tub)cD>aaWwpj1s<{y|IulqZZ->vksCG6jO#KAiTL5~<@Cd-L z2_lspzVsi}?lBt62Q!#8YlG{Irr=GptA(d~XkMRaT>8$M(N2(QN~gDin zPhCtEd64n-H)`kWp~m|&-3V0isW%e1>^g)niA`)_&F1_LiF3;m5ZH||6udtIqt8(l z4_Vm8kDpX=28WP{UM*3l3-4QmWuOt7xEF zKiAgyWI0!_&J-bV%*K7K2zNDJQ-p|R%iu1(*+|nTDaJC5#}y+Tj9lJaQrQP7LMe?u zD?;>g5;)E;ex?WyHHIoeU?>S(Gd0Fqm~Gcf<4hr#_;wr_Trr(Qj7WxC<8Y-SbOi}q z7KN8ln+At8b^)OrBr2&0Gc-0*gz%Nn;GpMTh;3$eoQ0ugbh50*kmm;@A<>(z zy|jpI{fPklvlQR;a0ag?!-0(6*e$0D3wPm}KMbk_A#g(Lhe5y=YlqQ7oQcr_4Pk4j zp&T;qyi%88;hV+cky3%b^g86^cg)Qt}d zC$Hkrlu2?gNvu&E1#chZCSpsRy=kHEJ~vj%&d~KFR6)Tcz3Q;=zzR3kan3^|FgQtC zZ<5N*i1Tn@94ikrepQhB1J3XbBveDeD%_D^w_Vj(1Xou9CL@IEC>RXeq5~SQ@hc!A zvdE3p!0iji0QI%3mKrQHPa|&+Lnnm#%V{5H%5n1>gPP{kPKP1TA1ZYnZb|bJWby5M8g)71Cho#Y0#l|=W zJ)9|TZrnWVsBZ~sY%?nvdmzr=G+o$f!sgaa6)5-m04G8@W{K~Af;!r1Bn9uLU}V!w z3)?H^ebb_53YB|74{&Psj)hAqC3AFa+D4_AbYm!ZHv=ONl#*#-9GG|>=bpt3{+Uca zFiyfPayGZH{yLeS_x;Rq#O_ECDp$$PKULOa;p1A#Z2zzb>S_*xH})PlwfJgm1uO^i z5<&|UOwreB;i&K2^q>*jsi7qZSMeww4HT%}k9_@|1WD<_XoZr_zpJQpxW;hYyF!E$ zy@M)RgJ5)3mu_K)jp9LXkzg4?;7+pJfW02uEN>%mXBlnIuf^haEyJ$Y{*M{VUzr3w6%g&3T;E za7eklJAiT)QzSboLF2V!5+Z+B2g*jv0_9-^! zH4+#cW(u=2n0at(Q{qSpw4)oX-S!Yz+Ao?KL!mr(+#c#^HdABPDayZN6@))O+_92l zu;zR#0v3nCk*pE7=yD6p1s8pmm-AjDDX{Hw^8S7tcR(!6pU{lHS_?XA!2#fW`ZEbe~yE0 zdZu(?aQE-ZQx&S-)z}>>5W+`CQ3baFv*TGm28qQq-Ugu(T-tsTxHouEugXqp%z4Po zIVVmC+%Sy50|A`9_nBHa3>9F69-xXoC>b52?(PO@?15V1)?tzmJ_jL}4lgY{1qa&# zrt~W`IQoJRij^OY-ooPuVL6@Q4;G(Bo_9Z7zpWE4g8@Q6jWO%pc64dvK{EQIU`=ne zhTNfXY1w4E6P6@|FF=SvxPqYAc3Gp>1~9;R)PbLuIb6xPIjgr;W>ukh}XC!&)QoUP&=6`vgo5E3`fDl z?rL3O;Y(Z|d}iP=5=MZq5-|m@$HL$`;;G|=FcJlaW~&AQDwpVq2nuZ+dYmdofiVIx z5vy-uD-aM=9wLEHH6{sjG#K|0@bP38`kr^&(VyWbsA>!flCfDpf`toaxpDWvd4>d! zd?t)TsAEAHfmIHv7S32EaY8Ye2UbGpqBbZwWo#EF~wkxOc25(5dOq- zCv<6dHHJ9c96oPJ@W5;pcABatgW-k1kymJ89kXGwy(J7s7*kME5mN$N-oklH-FCER zL@ZVKqu{csI?uv+D%MFC!c-70rl~l=!Y@ETZPuS*ZO~fL6uhT_nc52d&+0%BOxz^% zPqI+a27$kkIvtF9*b<^uT38IL3?DcdARa60cODErc^5;$ zo36~fsyuU*M1^q(3+QKlCm{fY=j~LZS!k;(ZIU2_Ss-+-p-$FIW7Sb^E_DLpc`gjI zFbdwYd9LkviGww_umTqNcrqnL7;{iC1`d@|jlah1&{Y~!*ShyO44cjVak}wv6k-wX2?y?%6l}zS@ z7=D>5z5`+7S!K-@zFR2HD@_Q&AoSJG4q6y;OwJK`g&G!tPz-~Rjcs9@W7zaUEt1Lb zz!=ID>S9oqJX9yMFr_g+_UeqeN?l7p=+Iy3vT!^$QwQLl3JL7v;6yS*z;wYlIZtoW z_+m77znlk1Fg@Vj5`?-G6nAH3Sr)#V=jMF;mIN}xu2JbSFh^ne#WmB{8mGWFm4w|0 zVL1xs`>TgC!Zf<`@W#6{;yN{if{+V4M!9J3l_&tCKT>OYVXQ#LQEVBp;D*NAd4&*t zgDO^{U<`JQNSLQF66b)g4NM}zg@Ts@6(K)%j!2xFTP@UtunHOGDQp?BBw1sxT*3&w zNfoP6;EOFI654C5oKpx%LRf=>1DMlDNYJ=Gn-IePpoX<5aAV<_6Zk^oZd3v-kw${) z9fp#tvz3b58bee|ME*$?>p=Kew?He6QK}^}g|Hrk>beCQY79~>5#y$Y4Ir%5E%Bqq zKB^_m;AAp3f-y$7z;umORZAoYVG{^{)>E~7pz)s^a-m_jsNs7MD%VhiIvO*w3n4`a zKY)<6iXs%y*de zvG6ADWgxhYOr?tLAk^1R)52U$C7{a`!Vc;lp+YDN^EGqhnI7ksd(gna90LJcuscC5 z{)M7i*j`azSk&PAJnJqntA(hqT({KtSv5Bo&Iv-;4Z>;+1FkE6()bk!n9;)?P{SS+ zR9>PyM}KI@&-VWd&vs%ZnIeo|ka7G|wbHfF7q!7I(c&~+@dyf)BdJR_qlI3l)l)*Y z02Im}JYhQN-g}Y!TQ`}7KkS45#nigxAvMGQMpN+K2WsW%Dqgbi)-P_(i;slq2YY%% zW)zrvhbg9oU#Q7z9|>&cIAQJw^Ty|jY2l*n*gC*G_fDuDu&~EedH~c}zRG}H8mn%R zc;XZZS^Yq;p|(jv{}qXJL($)990@w&>cvl32h=v4g7-l%zv`)&a}}DlP7xC9ToEdi zrU^9~R5z4y-ng%E@iv(^mOiCY)ONiH&>l&_`w*yI$E!p7YTUJ34!LF>a>qI(Qw}-I zTQD_xsg-qojSu&8SKPVd8I*cCpfo#7l?m@7NF?B)5{|4tH5O3Se@TJ|svrEE%%fmr z!DP$o=hf)7L+Wyv1hz>61=IT&DA{0e3}NzVjKj2tAah>2riM}QJ`TpHOcm@*)_5Ox z#;|30-eRT*^8}d3H>nYB;S5CN2qz+5P*n^F-Te_3(f<2V0G35Sjrc!Z7$=cYZK$f2 zg+m;&EZp>x)ye{ErQm%E%zk)uo)N5t1QN-zX*t5v7v<>l55s6cdTPF<(Tt0X4_b`hj3Wq7Hk;9 zx5fNJrN4ua1yK<95V~q?iB)(v7-c32@hB+RRyA8&jpl|4;?@&{aRH2`*fRF~0RP!5 zYmL82kl6hVbzKDGlJ;g6j@>8D>>>#?j}&2E0@JDcbcV+6z!G?B=PkDm?b*?>5pStA z0o)V1L*Hn;3B=CQEfPGl+t8Tl!o3V`3Sv+WvBH=>h>ws)5V-A~;?hJZdS5}=Dm}Ii zY1{-Xfpyw5O-3aG1D1n)6=a9@z7`gW6z}^h34FpMPMC>c?$F-X!Zmwj=`d#&nW$_i z1@CKMCTQ<#;hF7VVxQowP%%#=Q7CmC)S74?j>r)j%g=G!{gB25h0mtG8%WgEqqC{T zt+ z^EMb2PpUas1_AugvkqXA&)zv*q3lp(3hZRNW zLaMk2!ai6gyX>gOoPo)70ZBr*kAn6Xl_d1gm^?=a;onii0~C1Sz7z=`5$XT;D@K|y z(vUIeTNMP4(^v=RKzJD$Ocf77*x6O7c#3B|sA^WDWV-|AB7{fC=y6o79xbebroskt z%pz)d3_@${J$V65ONhpW!X*SRCgTZ84t>i#F#JC$8aH4^<1<)^5T2r7XMHzzt+8>W zaZ-P`y$_6I2{k-JL7hkHA&BuBo8Zn4nkq#I&q4U11>&FL5Dw!89MK=o`ygzI2%(B} zWJJOl76jhYSa+J-g-IvD_XP@k-l-m)qjA$h^*_s?$QHnV@aJcTDRb=ZT#Cay1CVe= zQ*^wf|9|mTsmP^OeEhEpOc<#o+Owc_UsCdL!k(5vFkV4(xIXlz#zPCE2|j~gIpP4m`P+* z`5TPiG{dcNZji3SY!o7P;;fHrcZKrw5W*>V|AX9Z`iOlROUaRVCW1_~Q6hz$4lwbT z9q$V`)8yDpn2l|)K4_W7P4jtLe3=i&;4OMQWaj*lGPgVdMgLv z+Lx>X)1D8P6h_IL4>hjQ$6O^2K#kUmxj3&1*MYuC5w0h=wKR93#`=o7b~Th`MY+un zvtR^MRr$?=`?@_#X!`je*T53KMa)z(coFFos`K^PqndhM<8aGfpp?#D{v2q0=dLw8 z7|kC|!JDVus1Mqu@vZ9hKS}V+!h@bu%u1s}%5(;<<)PVdXh|HxZm=+?>bPG?$SNmB z1H>^^HaqCszDSnkuZ1~ls{f3OiczJ|FzV$?=NoFN$kxIDY};`yPJ-#36O1!`-J;6E zYsKZ(UHCex$OS@R1vOEx(O4S$zX<=+gpeDAyJNJ!)wt|S2}dH=Q$rpQZer({jyPT8 zOK8Aq(aaP^UNAQ3Lt`}#R4QUNP{l_e?9qpw(zrmW2;N8n|MQ_v4EA&Fj%aB#sGhnoNmF>Z>=kH8!{|+E;A`p>V%1)Y7Nn5QWcwa`Q2dBo>RCijJS9~Q>SiIT!>!x!E!5Ame~#Oe+_IRVaT9J=VCj=41Xkc2BDfFn#3eUg z7;#4aNDZ|0N~i>PL+z*p@vVx!%uHc$qD{x_SO6G5SYZy#nh0KEwo*k_6l@x#4xKq% z;XQ;>m@R{UB7rehPHYZ3KENxuCtem4vJg0cR+hUZ4+&X#B^Lb;M%Xs0pn0Cbb{kb# zs8ys0fvdBZ)s+ehH6h|>YG8O-9`_~;;5m)K3vb!u;9i8l@G=Mbh%F$<=*H_u_0&TI zRpdd&_ovlO;awVU!U(x(yPbr*AT$}IwwUH=e0$GrZwq@60{f|*K1W}T-Cz%x144ID z1LxbR1Jo(Zu0xe@V6oiXP7(&IcNYI;Mk(MujY~shsD$sN3igvPx`WY8E_4U6*tf~{ zVR(jy1g=2Rgvr<>5q)1B7>T|ocAlARAAxrgb}i?F5uipwQcpV0Z9vP$t@VZqdzMb- zk~32Xg;8(>x{3kULKpGbH_7(Cu#(->Py`v1P%Up@Csd2L|3^1o_HhR9A)zQTwrCBr zse$dk57iljR~yJ+Z4!h^XkRfBIMgN+d<)H0y@VtbXk zMr)i0#7(NuDC%;cpfoaQTYWSxpD34@B!sdkXo!}l`4&QR65YXwZZTDb@23hno;lhq z2WYEo8qK%&oM}QR55g#@;5k}B1(|NB19gihPohpuKT6F?icqiQ~Ewr81=x2!FAA!ZycfUE`|eU+L#km zQ6B|?nlMlk4*eiE6@z0)XaK?>O=zkKF8CkVc!Cfbg75|{!BdC`>f^G*vVO<2%h5p$VrIAuyJNPe6F3E%cJM&?2g-;)Ku)gfvZv)dX)` z2JbkZp$0z?jt|86XEoPr#yt#0JVKZx3?~XAw2B~2Xo03e)ENF7RWt`7+dpdQV&Ryk zvg45^gccwy!ZU%4KP(Ib0U9FDQbS9wZeMj$4{3RHR#@0eHmoy+(F%ut0YAWLd922n z8)O?aCXOmvqhJccNiPzBbS=|xV+Uh3_#6pskWm%=MGaZep~T_{eh~a6oLi3FMenxA z8H8wo4m($(!doG??EPUA=c%F{3L2m#3IPkEC5Rs(#>I7{2%$YPJV2n6y$RbU?t$aO z6BrS{Q$q)2eD#GIKE2>N>BkF&!m6;lmoAKs$nnB7!l~cX*x@%f-V%03$5TZo6#R*O zct%P0G-kOcl?c2*LT40AJfc3|I7j13ATBgc2%myb7LJ5-+h=ejMDt5nCf=ubN`?of z!O)A;)dfY*F*7-URX`=4xhr8(k`THgV^MGQrIU3Uw*z5c;g_hP8wf)%+<86C&?LmT zSrX%%A%W*gyCm)39YrzlrtFzo`xJJDyG8RZP0-Xx3i4p#I&8~P*-niu;dikB$P_|P z6tqQ9Mk|;Mq|b~7VvP}VnHqW_V;`!;0BRYkWl|_LTb^3FM+WN^e1+7{P%>_adW+}^ zd^uy6^iuMKe1Z^qBcminDOF^^EQnECs3LKgOp;als@bRqOZL3x-Suk;-*h}a62g*i9+ z8a4Ds#$eovq6Q1UIViJT;B{&LFHn*jDj2<`LIv>-tQUP5cbzH*Afp5tjduSE)=S(U zENvEggM@*|xCR1GzE@XbxSIHrgfIvN=Wq%d?@wqdVySRUar~VHgP0CMf$l zsB!4}Lh?3H%pX)S9E_8fl}EF1nu{Mcbq4=Q!Uz!j(O;~@HVh@=h++~VCy>y1Br?1L zl{>Pqr|aYD*v<)aQ^P0_9_#D8YF+1Germ#*B81T(3`6bY6dE5dkvS|PnHt7`&`cKu zYMft;5BoXOg)kO`{V+F9a-r~e#BD3#hY_Ac-(oGtA?H^-sNwYi`mL(eCgHcv4g z`7^YJ9$G{3m7*YygvJv<7&b{Mu&|nIC^VR%Dbz3#gmv2FztmoL5HuiGOcKH*5PIrU z)Y7MTg)j|u4F8K7CWGLD$>}DXnN!Nd-uK!M)oT11) zp8QJ?dct{erLjR{^jFE85>kZl6$+m8Rpx48?nivD!x?d(8ombMh#oVgtud2^4HHf~ z!uSS^ni#pofw?hqiEZGb{9!5&sA48EHo^NbcFc)LmY4z{S}XK?9w`%V7%5yHLdi@k6QzK#4=2V*waE$J>cAwIvB*7BW`Ck$wc6 z3Maf^yB_`Jr;$~mM7VGauF-&gZh>-)H=MHRajizAJEOcjC1 zsQy&_hv}^~Cc0F3DulTpyf~r$hxL6i3Ugt*f^*9gYM2MYFkFUI0+&I2iP;HpMDSA* z<|88RC};`?L27#&R(3V&ja_*n*l0Hv?f-kr`AGih@ww$>OMJfXBIr-GK07nL=1WLRnSN zqmsf2KoDYHQ^QIS24i&4n}34QLCo($*j)xj@i!SRCFUXoEMF?w9&=WHwZGNU8>@P3+1Ew31 zNfm2R@*7HIl%qw6pI`}zJ?3;FgdwBxcvY}n<6Lw(2+?n-VI2s=pn~9F&6~(*CVtDu@R;O z+|x@E!X{*F0-+)>Co~W@VmAI3HW3gC4c{Z9SqxNjY}!t$G3tvjn_)(PtAAa*myi#0 zDK0B=77qvqttC#y0l6I-iC@p;*MyvzLfDLq-k61H$m=xDgZsmNVa#l5*n)yvs1qB% z12hm@VS$VwFnA6LKO&<(PQgL4VHjK!g;Th02fTtXwjv`QZk&hu!i^Ivqwzrq3#5vl zkg?;UdVJ-8#<_#l>xe?w20|Cqj+5yMjeAf_E>PxD!_O%A=`B^mG|q^C;f3CTm8Azr&#Cxq56?JE!wW*nx}_I(T}mgQuUcXvJ;cI3er= z;f&cs^-7Y)d5gr)hXzr_E-O1#u->LV6sUP!fp^wqqR9wYofJ@wa}I=U;zuL zVGlC;Y6rShJJ4tqai9&c+;@BvI0}We54F^z=id7W{WKT2^F#)Fi9ij&z{ECcO9%>hNjmB4< z@NKD&VHAt0;vg6vRn_avA8DLcjh|g}rVAk&1io6u(X>osUW71MxkWFbhC?WL7_Myl zAB_iba|>M_7(&8f5Qd>UIIh;BJ7j9y1O~1nP8df}QW*?-gZ^L;3xr6R6uOiujv}Ks z8k6p?E*g_qAB~B4I7tY{ka2pTil|>`tT|3@8-*{UhT|Y4qJWo?)kLI4VI&xMrYlVt zCy?<+Pt{SavB}F0TRc~7eJ-bp7-V$2s;(nbQ_I0?deEG;-HZfl(Al6g5M zlp0QhU%q7uzv6RW7<90(scJK*y~faKro@A3!ng#+(7S56{I$mGxDkZuDl&{J5kc0v|7QHm-KQKgzB{oZN5WR^S zZX#pI6V+6~8V7&E(c%pJo`gR@c(zBGU6Egan5Jy`LZnCIgz+aboN$DUFDzWOLMF-3 zAE?5Of{Sp7bRf;(5Q%%S=hzE2A%tXPbRAE}fz1kyADxp)GCZ6bZlRzl3TSTT0WDmJ z6VIO}jN2&Lh=O9kk`olRfC}8-h}=vSDJUq@S;f?~G_G7EyD^zU_zQ$aSo=^zca3|o zM}deWW(zgkLBWin2ovZ@k}<^*NB$*GBnSUU#$9AAgjw+dJHV`n8#=n>7Ksp2k&#am zE@&Kek{^+DhHa&WdmwDo1%tGPKew>f&J-csXPA(P2OBy4q-gBZRs|G4QN;rktVe6p z?sB2EiOt5y9(TGB(vWcmcE^IvusdR-aOu$KZPf4(8B^fbIlX=gqahYte9OKLHt}=l z=U_ZS&UjRl2oRb)0im=WU>!9kxqkWt z<12{-@24Pa?WMxIy&B))p+m%r;oC`g2EtC8dIZYCZ&%9TNE5S%4qXfP?~={4 z$Q{&>j)F(+)x&NUj!DD#LU@-cj2B>B2ZK&IMdRtByk2L_PO5l`g3Xu_9KZyP1z?wO zslmHQc!dH71_vA2!o@AcS0xA`0|l?fD}o@$mu7_Rri$0dIMq`zEYyS)A^Z(O!@Ij-(Inx(uFk35AJWX89_ z_{xurTgbo^o+J!AGA2VGJ&c7nf0E6h@O@O_iGs(om94+ixPGtPyi5}Ut8IPU%EDB% zKmpie6f}4Qz)w){_G0^|Oi)k#d^b_y?Va*OdZsW~i}{&q+_*IMIxDO6nEg~iZ(RO_ z>IXyPc=#f0HUu9afl}7|$x}9gg)642)wd0!COVodhLqm=DQyeC`hXR9h%AnXAK}2L%fbO*nOr$g zS)9-~1E156XIt3v17)Fysf;F5`ctLM!YUuIl7z+3X?`umvM}!ltneeyWtQeF^BtmY z*381^{{LQO8fm5J{r|>}16dX(e!z-63YL7MDhyrBso+ga6pHX+ctS|3^xr2XkH zF2x+93ifQjxys{@)c9bsjIQA0Byh&EK3!yC$M2PoA)yp!ee26b7LGqm6Oe{}N0J9x zJnRGn)0-Vo44Cox7w|>un}H>!^uKVQ&m|I(#ohHsHN#pg8pz%k}%4Faki3jkk>Sh zUN0+v@K~xS55gyP)h*OEhh^*wvhG69btOF6`cjMoDX#V z_nR!RzwP;yyFeK>3vJFLqdhR9U;@YCuKV+?*duVzB?q&{GEhc+221KjVhqUmPRvmC|`J=u5LB;LK)>c?STVWY>_x=b8?2i;-b^voEdW^AJAdtp*!9>>~MxOsC zsqjw`6udj4sJJ!<>%D~{${gZJ@C;xhrwg|exOa7rSg$K2szzSzrq;5sQws8o%Sz3Z zmlSZMxkgcwh1whjn@sAbD5{~U);kJ*iun@>9)Xych1mtnJG!;3*AwiD`AnF!+*{Py z70hVOwBAmLF;#E(zs5V8Wfn z3KMObCd?jS+%nVx$HM+EO}Rr7nL=GX!D!J@nQL#2J@(6My_rJj1%mapCkypgpThrQ zwP=_W7#snwnb3*HCu6 z;)F2}jQ!ZkV{md^^OfrVxs36U-upoL1d--W;Bn$6j0a+4Ak2J16{ErUKfc72B7`v@#MD($L!8F% zkIQm6;wd$Z1>yhuQ%(3k1W6bNLRAbZuMhBb0jyN9;~V{qjPWSRfH^R9@y7KK*C&cu z1U@HW0y3r`B;cU3(6_SsNSP2OqQLqJk%gWZAh@FvnobRqK=}P*wKhl+MEf`WnoB!p zk}xKN(f_6ja>r=AoRxQRoZ&C1VhRZD(Rew4Jv4Sj@B@dFCIo*JSYHUT(D$&ILgY(o zm71RG8y3Pd7=Ia0dGq`cvH$q{^ zT148k&u!n7ic(7ZzVDmd!C2y28^$t~7)y*LCJnAkOsJ+PlcZ6DNn(mLLMHyt*ZZ8K zzWpD+`*`sBoX>fF-k-(I~G5{H=?xxIeuM-`R*dyR&fEWCc{k&f3fD!{<0hq$m zJ@)tM=CC0@qG3(_ft^^+UYU569cQ!PBuC?NuXmt0HRT4pMnw2}NzmjUHpR^QOBQ+n z#F?XM+z#qLQc@y7-DSMe(APn3XC+=^<3nEepJM)Da-VGVB;v|v-4gcgUS9)X_|B{n zpoa7W5wh^A*RcRRky~s)1`*XBcQc+Ny?#-HPr$GepY^v)^n&=67+rCd*F3r%%BA%0 ztn48-w>{y|t0vlOq_AJ8jIc|<#v0nxElz(O>>i0Y0Fc%fU?t67 zXZXSEFSO-Gg!z#lRpRVnnE!rCz<)`gC}Si*f9NyF+PK<+Hl%0GatjK*L=0d@$~@QA zKjC#7&(j=AuVBC%#HUVlqg~Mbi|kqLoZhl95a8Ee-5S~7UXQSOeyrSpK@@9BbhG~( zgkGQK9t~9_uMZ}o2}}%QY-3Rsj`%rD21?HsNhlXCX3ESShbVGOru2 zfUu-CqC>#e^8g9fRv8vaFnnWfOW-p5iW>@dg}Gv}(b^G7&{bn@wgNI&tPOieruX&E z8Gi_kaM;d4W^hj+v-*h~PE4399oNnE@*6T`Gaj2KLPiV2MyVY$f@8w;>F?X!F<;m* zu>%71=A!#?Y;J#@=1sz39`z($iaY}E2`m?Is2fDs%OMqZNIZ*BJNiT=z6~m;@*ajR zI<%n!{(DTm_B0&{66RnHn2YJqbh~ag_;D7EQ)2B2oGyMAc9ZXV3;SDcPJ08OU1~bx zl(y_qoG@WK#G@Ta2^s&h0KJcs7?{1|mbP`zDj*|RlbAKo@1JiQoV7$7r;Q;MVMaH> z`_?b_&A#x~w)Gq33=%OG;#$9y-4jBWeIBKJe0KV+w90ZpO~Sqyp1V*r(BVD}Hz*A$ zn&=-qCN0B` zk)3s0+r}s650{Ba5WE*}m2QbA8fUMPi7Epo1BAEYXL?}%fb1i0C!IwjWMT?Lcq@La zCvF^&eXWSZn94En!0e`XknCbZW`l(H-^)C)ay- zw;@g}HDV4#c*niK6NhK7yMx@z9U~KS0m57DxgN+JkX`pqPEuh+K16t#eV8XM7?9ls z;$2@X2gC3w4`d;lPpIUcm}V$xCQQylc%xFwkweq`8(A~g#x)<(TT_Llgh2YuC& z9y=hQTAEfI-WB>WXtO4+Cky(;S@t2m1p-p<#C zL}dP`2ItgiLr$G{0H))aq;9-#mFs5^{-h3 zy^AEYWPh64Ugmo`k@DyUf1;qv{E5=+M8(Fb^_1b|>4ZV+HqkXx+tbpSg=S5Yy;@q5 z?7|I3fkEHKpg;@)mI`d7MwaucyTYJn`}C#AmCcpKmx*-=~ujL5*-5ytJOMTT-P)=$`CXG%_VK=o68RdR8bmUnc4k(Ujs-B?wxbsT3=| z6#~*U(6{O8vMT6IdKcY%NG;p`GkwPgBlQ)}li2aF&yk?7xeTd-a4*b{@EH>M5 z6wMQ$CG@|%yBc&=1J`AID4-EQdwMiEAwjE=gXg4lkChmaM$DHyEg>T4Mbz4xs2T;j zoW?}lT;-~3(2l+_RxgWhqTevC30!|aYwiC~_V5SPZ_Jm4lZk1RVguFyhVZ*xL@p43t? z_oBSUU6;Q~K<#~xy4D@^WgggO9W*PM-TgrtMb;3FEV0t0jHxH=z0CEuLAx%nR+GC3 zpn>YhpBc_z&_VecU~G`vA?TzzcesVspr7UG9+mwxjC`asscSxrCo|&e6SN_HXs!)a zRU#TGEjQx0C?e=9Gu^4|BR)log(*ev)Ab4qI)D=@MV6*SAy@;okBSy9T|qZ+AI$!Y zFJpd*Q8Lmy({*z}r*nC#b!k+OkCk*4)?3`6{kL94Zw63qfO?F@b6ouiT0r=4{FWuM zpg!lMm^IpX*hpEOYfn5^8li6aogVJ0f~G!iD}2eNGNHD(?O6vL)aMMyEE1r;_!~Yb ztxGzn4k$K2)qmeQdOTgnzI9IfvIbs<%JGRzs8?Rt)tLyo*qJCbK)v#sjt&TVkpps< z$%1<2&sm&OB7(MbK!pMP2?V|y-PaL8+qetOUoI2srzf>_sS8@yrLxKZ_0!dQISWBg za2ASI$b$Om(cVJPRA(XaXJ9Xf%Jra;9ri?K$)^I;Pj}tt5)pLm8@5iB^O*qk z)3tn85Hv|;Rh=+E{q!-{xKjkZX0X-2Sl;I{p^o||nwE+q=oQpGOjH`6e!3A00Lsju zp8>FDn=Hmcn)>PPFK@I7L(uo;x~_q!bh?Z$#M!)z#HxkGkM$dWlUns5{BWC#1zLCA z8z)tbC+Gw3*phqJmjcwP=ljtoXzP>gJ+e{*)NmI2ZY=2LEW4=Om9h|5J3a8AyQv*? z3~6b?;9^7?z&v^sHJYGXXy5?(t7Jmm^@L6i2>LQUJwTNKO#mv$Sru>4hsZdbprZI! zGI267&B!^m+@Sr*IUKyi*89AJsJ z5OjEdo^fbS6)~a(L~~CB?K0e!GV@Agq9wrKJKZ^go`Ji}(?gX8XmB{*CnD&jE)mIZ zWZ@KmMt({65mVaVi=SJ0WUdi$D#SJ2-DKl#uZ4^V%;Sm;XbsSXI-#t3!0V&G*cx}% zx3bWNi1V2zsdMP*wdfU_VwDC_%pquZ7D;*H zs=|PF00aG74ndC{W9P{K4hs!5RXuojj@gQ;`k_o5RKw}*s|;#SAbu3}Uo9%=dg`9) zB+ag9of2~ffnHy^*93xg8e!9n#Plw=2i4s=2}S5p42R^F@IzB4NtYL8*R!HE!@Pd+L-+`!FabEt2ITN zbh!Gt4$Nsac3$gsZeM*cE0!n+XrRm+xyQART(7&hccOj}*QUfEUEJ?PYWO_h^|*NUUGRv@(4YZQ zMXxkU=cwRrw^A0=Q5t@6C6hm6tcfmrNNa}$J!nkH(Fn3drI zRbb8BjQ>2?5KlR`$ZCJ$R}u0v)<5f7anL+oex!Mn7$866#2(HO3Hk?J2|ioSZ?Ygi ztJhCv+Q-Yv1*FN%XvK|<>ZWw6+Bl=95@A15o3~w{+>O(?Q?K}-yBI3| zaS|%U+3c{#W3G1#dOu;-oRT{P$nbt&`+`PzID=jxGyb~>nOsHENYwjO1 zkw(l2|IA3xueqVbbyOH2KVt(8QW+AoFkwJ`r7XzLxQ50kAn4r=s50PWBAWVBIHms0 zapx%7B@^;9a%h4w5%gvUB>oi8jEEvyo`9ff4k$68IT0ghbOM5=I3Q=YEVLk^HkmA- zcHD22@nu*pwA={!84=cmL5xHI? zUTmuE7~9`{34ji&Ogkb?UWse)kL|Ef=3-mL%&pSFsT{n>T!UDF?dWW=<~>x{4%MV* zNFcpH#^17bAMb=8MbDu?RLS1j(_&ZHj)9z9eHfF#D%+uScaJ**!}iO-)y}{Q3*7Rs z9lTb7==kT{!E|7W1KOeF-Q41JpnNu-3iCa^ZJQk4AAA zvod8t!|j@z{Y{n5PPY+$7ze7<2#s&Wn9$I0Du+t{B#i5j+gBzu)YiMtIi+b{t9Z@j zeEJ6i)Hw~~NF^p{XI8g4MSj2RvX}5S9$%mjeeh$zs_G}J>hcCL{HwkM&7WuQ;T824 zph5JEzns%`q1XF9->BDE69WJm$j`opB{NwFdL8Fck4I--BFHAr?;N+lctZ!L$Fy)Cjxa#^(4dv`8-w1?-3UD$F;EsXM!vY$oj>UHbq%OA zKts`?x43}@b<3dFerGowl7nPI^Y43TAIjoqy}qzU@2kfKBm{iQ3V|ZmdA-vjSzKg* z5Mb4HRUZd!@Ort27|pW=3sQA`yEjc5%%Agi{EX{3Ta^*VhGLoUzizF4(41M@9=!8 z1Xq@tZ0}3Ro!*WUIpy;`mqBN!v)Cv5IQpfW8z`M5hX?_rd4-G zJmmEm2jq;93HgSnuu>_oqt~k)P;P)K^5Jy(0vZQ(K;E0Opo-jyF9+DOTHV+Xxp%8w zN2L*}$&>sA&i49^Gm*@a3H6`%_zQg8>kJ2EjufEU+`wO7ORs$$P;3CTIi9kfNsdl_ z=ABOObVSxDnNW3}%W8sv?OxAvK&b($&Kui1;8(9lI3PD$7F3(-`|E4w^(S|o6#y)Q z%gx)-!kO6T^(#l@kCq9!d9mhhDi-w3dG-)t#u$JGcjK_B@&p}qv6lYakD6R$kowbS z{A4j`-oKUHy!jy zUXW68(HP1NQe>ywfi&dU2D;zQV}nIrjuNA5>W71;a|SJU=c+V79eH?|tmK~Jrpjn)Q!J^m*6@B~8ZWTD_Aq#DA%z6hC zcAslzKX<`FJC~K=ue#se^d$zWQM~2Bpz(|Um&_fnRH=3RXKs+vte%y4g#l_Dw@~Uz zeb8fh5{|X|{C8zRx!s+coyzE-eXH4{kW~h#aqMiv$32wEY?$_+uLs{^MH4X5NPT@R zUywn&VWJiLt+P!`1WQvB*?F5gQ_yx`r-+KyID|pRIJK0=A9Lpk`fxh+PX?HGG6BfR z#b9IQ+g%U16}+G~r-%GJ`ZButa)FIh#TQeFRLDVF9R$-Dk|qgL^LZX;Us%uzT8NcT zTs>>0xF(t`bw9;%K{uu9ZChGfUjgzPTOF|3aTBspEVT|wk*5UKf!lUNwu<(a#5ucXS1bdJ}p6?;Z!`O zo%@~ujULbWv;>_=`EcD8?~P*0-B{D54rGw(O3<2CSJ*+LCByTl$&{RkhrOww+W{|T za1xM~25{ZYu8f1GQX;O1kItZKO^0jT815=7V%opk;5Eg66`lH{JdsTxr}{Dudi+5! zUCR|E2C9@E^Q9d0+fd4QSU5j9Gi0$TU>9G^T~1;Ax9a1|nK*m7MWoHHYT#t4`w9BH z>wfZP3TRG5@9WBJ8X0t!E5u3zG`qUm_uN50<#r^UOLCShv{e5$cxjo{l%Nx7g)A~< z&K9B8Hl2}2U0u*?M%fM9VguC9F7T@aLGORjCNEj9)kE|ZHJSNnN2J9-b7V^u zh&R&IYM}3xf}UCyDjG$WJ4flz1Zx6Ct4b2I9o-$plyODZ_*BZClT3!BJ zS!fIJ-zSOBjJpN3DkIuK{Pz*zhbSs7&F9O+=>Q)-?h+C7W)g){o%ldNdw^qjbUT*|D7gL0#-&+$fUX@r1onQ*OXn z>{vpCMvS1t-zwAELEeY5p!M4->ZpLAJ*XBqu$2aA{kF+v2E@Zg$}JIn>o=Axkckcu zg=ac9I_T+zHia25AE5SHdTdqPpw%kPOD|TWEqvZbS1TZBQwL-%5TH?h4&I7A7~(cq zA%kd2w_=3q{BBk+RNO(UKeJI!CQn_c1k~v5B7@#en8*r6S^|=0lY}`(sR8mQ{=Ctd2zo5n1&~`L3-TvM_{#{oj4(ij0dgnK zXzeTneXTY9FGT()GNDnTcS}bEeVZ^ql>r+2x-@Y>&}Rq(6fKhlHT&t9)P)8;(PdR) zxd6Eg!+lnns{Z}J4os97A#Wku=T*?}2m|D-kO{d7C;F@k+Qwy7xdG}?zV=xabQ57L za#1y__(w4V4}ErDGM6!cirPo5wym=c8bI*`9C(!7w&iG2)cqW=O|ev6B_3iyx@SKO9%tx zd?i5R{N%pw96=Wn<}%6+XbDi^FC%EBE+bB*_*y13&fns%BWQPb9hC-XoL|UdhO#Q? z62hD#xmp%9&VS?25p=!Fs>~7r8tFUuQv{8tyK@v9p+SBq&nM~}K}Qkh99iGUga-K= z{5gW&>dsMWfCl-!KC6PJx>Mw?kp+$M*OF{iJJi*`ZR}tISz&|*`PVtAh@iQI0rJ0< z2@UdndpjWL$Akf@4A3CI{V4|ot;662P_$MSG{!%6mH_IX+hD9<2SnmK5gO$G@C_{J zUcvw+256AK%@038eHfcghfv_U2=gSf^gGw2w? z0EvwPE(aJ!WmoG6I*Tx^qeMW1D~R~-GWmgd?gc+)G~+h`)$VekTUX6DrT#VRXRE^H ziZ##a?&WS`AG8h&7N=1s$_2=Ed*n$u@MM|S@~7-haisuz1a9w6*I5P48XfNFF%3%o z1lC0E)8p^6{;C{f!}O+ik%kkRug70TlFk<|&Q&Q{w{krd941*^)=~<}2<6y%k=6 zjixk?fASRPT}HH7a(=&V(S z%E#KmtU#9YaD5S7q5(#rF!(_2pE^qFk=;nIx!uf^O}j=i&9kV7Xy(ydGTc3OMMl zamreLadCOSVy>~=ug{p*$ny?5n|Vzmas1Mmz6fk2H|%b1rwR<(uf8r-KkOxc6DDVD z^cQX#6tq3J0_3|GmbqQ)pSFzi3i+T)5_En&JvQdKVmP;qQ|mMLG-}XeG3S!US+jNs zlY6%30+%U4r%?{>Mm1Qeu*P!Ix_4#%r%dd@hV<`K^su%2rBUC07paE!)K(4l^yglm zYwZ^Ig#uO>sLQ_#K(6v6ueSs0RQdtt@03Mlz%5&x#rR~u(G*gHj((6;Mk>)`yE*bb zuMYu;>q&ls9+u-!60Nd7XTUmJtquiAsUW)El{6)#s;l{n}U!DgQ%1OqLj_ ze7&5+DPu-@ZO6I)l|ebXWHJq49gF8`n1^wgnA7I6Ws0nGunT;r;J&|$r;v&h;j3-SVoa`#UCP0+un zdd&Mv4UiZ3#4}nc;2jvJ@svK-+9wBc|H4EQl|roy_qDtsUYpYRb)EK0r?!c-hxg8g z(2OSObpj+;oWDPVW8nC!Ke1F8fxQQf#FPK+Ar&t5k{ga)tW`l2eK@(Zu?#MfSz z{+r~iiNAGLW&AvDr791CMrq7?X2k$Gh<9*&Qmcao4R0v$ddMH@SyAf;Qsu8E(<$9T1?3df{`f$b;U(^I_a?t297vV*J&8u0(^j ze%V!{cy_O2rrqc%>6hIgo4e_!yI@X#*-6JvV;(C|wqD}3Wm9`h zv)q6f5$%akXMMBRP5^ijc>`qO5+WXc)r}i{y{>z#Oy8ZU6wu^SfUlo+c~JH=6!O2pq@=i!|4uvl(FCaxyp9O{uq zgv-31Ks}<;RtRW(4G~M;b6?1a##13HXibR^3W)aoWxj#{9Y&FtwUMpAOS};1Q;_Yr>xAc-DWUM+nnggf~90wpx z0I;l_`KADMskND-%1;XV=(DyaT>NIX7BbYQ{?gKYv33on)MwNutgnG&$%M+|8Xs{E z=MXTRbMUZNsR6Qm&)yAoML`QDZ`6x&*&}s9chgjJwPm+fi!rY1GQSlQ32ofOj<(bn zBjgCwVp@>;FFlZJecaShm{1p%uMJxR{eVNY_%?y`NgpA7^yO6o>>lg?^=uI=y-hq; zlr2+A#b}APLk{l-sa>5I^KKT;6Q9k;{GBFp*!#tTeA~dYmz1H;^F|Q5Z z->65FiVaY!I`S4*f?^kWzTJ*KHrzw}C4J+Y0FhrUbgk zU0&aux=}CX<-a39zV-^9Ta~2^ru2X3j|d+al}NO9eDmo7OLle;JQEaHQAHi|vnA=1w%wXI*2!Nz@BjT;TQ39PTW$khooB zLj#)-{a}^Lz*oIKO!hFbos$c7vQa9a6xHJ5E8Kjh-0P88WM+FnXhWk^lh0#aLiMtv z*T+V0)YrmROoD1)pNEwXy>O4aj8$Hf<2I^G7&`f2;^at&C;Ni>C;Uo89n2Lu)bBGa zs@`>DSd`Y8?Y?q01<>Asxsj*uNMbz2Z>03ev*$Z1jF3Y;wYzIaL0=+8c=h>HW#SZo zT68&TiMzaZpes_>W5B6IblBwvsmr}?##3PEEqYHDS_6F7l3J>MVHqZ*_c6E7UCC)8 z+OVUJkErhZ{wL{n>6c3kI1OOx4L+4#w=J*-^F~d_f=%^V*aEwg1q}`14|}asrtFTD z$Hm#|>gXF?m7M1Fgg5PS^YR3o&Y=&kF0&r?b+1>kdU6%xlmYUZ?^vYkXAh_WkH^B&#i7*qsZ%z=q1z)1LOs-uW*^YJ?=LW&zDuh4=S1?6Y_ok4<|A)SAhK8 zdVjiJyo1;C83!0|OANS3z&Xy#{Ld4aIr&&+M|?W+BmtD!Ixwj#U^SKlrj%4(Q~y zpJ^F7wI}`nxt&M~ z=m_v_Z)ahX*BiM@LMlrPxE|nKpUIb_ab0j9+Y!rIBojBVqqWcF4qh)ajg=eF31FPh z?I~VAHI3zcBnvkJJmz!xC9h*lW0eNn1n?s+Dd&!-Y;zkar=D%eOfHs*n;}~GTt36= z#ip^$LIIrt4)M8stk;Gvw~Gzv0&vyIE+;yBt<%&_k@c}G+yc;}VcZb|d~T0+xm{|+ ztq{F#bGbdrYh`!K?c60Y(G}ncpUba!9b_7-FyJjOa$hA*Vaw7_X;un}i}SDw2si0Jd@Evhb(Z$4)gM@ri&tiO8aw z33$ir+1v!dLdhp_5#5Oy)5sBXyv}NDM9wk+cL8)h$pKGzO>$QR6XgP$+${??yVd8Q ztKW0p!69-waOj3Fhpb+skYVR-ZMKuUn>}hWPm`zlLxVo|pF=kvbc4_P%u>BEM4)nW^e@9}Xp@Q0wUiu#!f3C=mO=(-_ z*#15~=*0K3ADPm&LHwgn&G6A_HQw0%8Utc#IwJ^nBAyR=YOt&67HQk3&Fg$IFpdJ91Z1q=S_KGt#Z>L-=$N{M}W&_*v(;V$nXY*g{Eg+f7(`;U!LpNDhz z+WwqB?qT?A@yc~v(4(ih!nEA4L7%7NnmnQge1cDA&~E+|<|~5c7lYb&RgYlY)I_Vk z*N=zW>seI>JVwO4)7=VR&}H~!tacQAAq$TK6g=Y==7LUsn+7b0=}U;VPe7cF+gkl! znuQ7Z?Dn%Hv6az_87ouL5*=n=TV2%JxoScC&a^)`le1F5QyenyFSk?{G=am;yrMjA z#M2PtasO1+2e)#1(^=*f>hwv(9HAQP=q6abUs1a&&K|6lrUVQmh!0SYerd)I#K^p;Rwq`(2B1W(rtjh>G zWwG5?%ULT6>cM|n?koh2k6vVR%5ozzAkJRzYIe}&0IXLH{|*zW^Z|L=sMiZ}FAv)* zH9_}4vb z=|(-#SZqLFfc8vJwfYnEogAwJS*5bjkBCKAyQ~R%$=r>6u?Mfpi2e|#`0NjQC)aZx zt3m5!VgSHlWWUZ4^i%*QoD~MVLB!7Q-HV|?Uzuh={tvP+5Fm&0QI-WQi&H@O!c|5L zB4)O4-a#9>=3VroOe6qGeF+8~m$Y*v$^;AsXy*$s=obKIq{QY6NTmQvj2r^F<1bcq zl^ixqQ@J22b=C&ZgC#f=;BlY*K~u;AU2PmD-@&m;~_LYi7BCEFzXwxI_effjYqD z6dN!SV7>1sg5ETRPFYLLKgq->h!<(*>PmusM@6Jgml}{w#Ize65VRGm9jsvHZkC17 z0QdTw2znJc!6_;X7z2>G(A9NQwaE@|SznX?vrLR-$1-|V^#ehlXJv?UR2eXih(xxl zh(RMHLO1HS$U+XlJ6&8VgSMDs53whH5%3m3w@Y13jfahBw!J%1V#M1JJ+E_(Hs~|& z*(^I}t4zED@Hx4y))2ISI&mF!!hrEaH2cJ@Xk6yC`lDslo}mNTCJXNZbiJNgwFaWB z>)k*!ve;fQtTbW*5tsUixYyepkgSl2i2!G?=qL+MdcB~zeFH7?R{^<1%;ko^T!ElP zWHxPfxqyZ>a0*gWCK286ShxDu#_QFrJJVLOev_Ta07+IvbfT}k9-tmvLB%j&3K1oD zxz(sGUaQc?RE+IdXgn2Q`*$V+)QFO(t?iqm%c&b>EW{fI7rPRwhdKWl_wrH zvM1ZE-Ev{}M~|1$p<5&H`U35!DYd6k!22A!g!RV5{-p=rx4&0VX}}yJw$hdA96^Ut zK`D{sE?JmMM2AZ1p9nTg>)Z+B2N9vHMF3umYE-z zwObbE0Zd`+(}*0jHyu8gQEI@4%KyY^jtF{3vHO$mdt{=3Lr3BO=|Y1(Plv8?)`0m$ zyyCm>pkv7@e69SwvakRkN>=GIg8oWoQzkq1%Ky<_iYh}Ff_zMNt0NCOirPTmGwUyG zRWCare?^=1k}ysEfEje3tEY*50u}*u@%b9`dFtuKET{_5X-oFmtnMSw9e(@{x{Jz1 zWgS-K(Hw2mTMW6~mr2k|FbcUgkmW`eLOz5|b>>0uEU=u-`&*_yCZha$RyCC|<=*B} zch)T;l)y?ump}|=c~)f5fixyY)#QHJT1vzYhFzU3Xmc`7b?JbBA|igg+yOy9!a{5E zvrvRiR&3}epvBc)vVtb_HF-Y8=b$F~iRzm!6yK9v}Z>M)*O?|ZheUf*h zHcre)Sp{1OE5{`0>#z(S~?LqKKyI=pFAJ* zluxW_Pw($df2a+IuLeIITq8%&yOztzjr|eu1OMP9V14wNDe-;i+NIlZBoS2%j26n7ZbkK7@wPyc$V87J{gD=1MxBS<{+Yb7+ zv;F2kZ+n6^POO!(7WQHaO#NxlZHjs3vSIqcijCE7qjn0b_dO9e6QQm*Xnf(uYIib(CS)grh?G+Pjqy~_^-y>5_n`)h zlJk+Wo_~Xxgev7hhfw7@(f(KdgZ)7C^BB`88?-jY9!ZG}8iKLZbOuswxXk+z>@s`> z4YxtRnqXe@k4D+K%ZS~|y((R3(6L`wu1y&lm$5Xx`niGVtCzWR2R-J?jn!`EzS~ey zcnqm28=>}KOeqX{1;(I09OkK7DVvDxIMMlZL1Rq%=uI+*L)9w>I1j-7sI_gdqZS0c zNU;$=v7-eJjM`PuTj?>G6%HMt6WO(GCU!gBmZ+fX$J^jmD$4#cbTgJ11O$B&fIHc_ zZvw>YZ6RhUox6yjli#r$(G?=>PeV_y?#eFca{#0yKTE(?j_k=Gt_%)(?7P-uR~fL4 zi0VA>B_L?tB+h$y{{59;#{Ekmm<`z zN)6o&n*E)deg!>tqAgd9%JF2bHtOwxtn-6QR?xl_8RK+?0eb=d@^hr1SuEI`LcMuQ z7XAW=e@W%kr3YQb4R}hV%7}eLyz;b5P0+F9%!@60TPCUiHgRRu|D}JCTt4}hct^nB zM4ZGa1OzRkd&Q+I5pY+%{lvWYha-XxW4ef^oHJe~4gd_s-%x)YG&B2V)d4>C7Zr3f1%4wn zVxoW=0CoLE1)a<($ofJ7=1gg$VFdEwUl`zv2DPz1t9dx?7a9oz6 z*)pN5+K>C8LaWLjf%T zUh^GD&~xZOXxtSBv;z3G>jwL}L(tXq{7ji<6ks83fU<&hakzb#yJm(SY3*%qq212f zQIMTl)b{xJJ7m2&m7tH}+-gN~zEaW}1EcWv1O&ap0f_|y+5p^4LlzM9QEDr9U`h-) z4d8XW8@2SH7c!MhqoORtLcCsEh(}pyw7$UWcchVqx>iIp^(Ne)w*TA7+_$b6f{rD3 z89?%qO3>*54Sj-wE+s(#l?Jp2II5#N9qPXFbtHWc!(4KaOq>C61(ifa9dr)4OOi7` z5^yF!n^bqvK_91U(TcSJX91)!%qdrbp2sjp2@hM01^dF+*+4V?V1yGjgK=E?5a*$# ze=Ca4pWiuPYnYbl`h$MQ0()0Q@}mQMrx4mrp*lc!ZRMI>(6Ue5lE0|tIthtNIT!F@ zd>s3ecG{5r_Ds9GDV`p0*2gkx_2@jR^wpyNx^E0CMYWCb|z=c?F*J+E8d_U1QK*E1AZS zu9=@fagizH>@{$GXyQsx&}V4kG>hHBT*9t}y6YilEod8ek%gb@lr=DQ9ni^C4V^OR zST~mTFLtKlM0Er^jxIsT5BfbN$%tAatlsqi$20D$41&JJ(g>aZ*e?K1%t*NbWH3!$ zRV(OrMrAyjO+xCYc7j*~p)n}vQJ=c&pZ=wg8aIMug6KR!mt%zU{4V0844z|$N%|87 zeSp;uPPAa9(vq5TGsvs{OhMnm3>n>fm5^#Fok6aWC!_1P4Yb~8*7X;Qsn-Q!u1`zQ z+MI{9jQC1MYNXr(asx(m%|SO{gQTo8q*ltUAX~Ab!VLNfImZYy;cHomr=@g-De}n; zI*2oo+^xnOopKw<#l8T7{_YB3&T5%SPq`f=|4Ns=K~I~sLHC+7N*V9|aK2*gg^4@oyE{ewyx#b|xygxd1gOn#ZR4I0XnC5``Rnb8-x32fejQ6hZM2iu zHa~38L+v?hWI@&IZ!G9$)cF9?opDUyikBOqdU{Y%zd?4>znNT+V{E+*b zshgj3+PZv$ZV6NxprWX8p<7Hi)@yq%l#wU7Ru)vXc3kdm?;UnUS+)3)?05?T6Pe$M zQ2ji!iMzlny`JMPwAcWxL#!kH>PCL{`Un@wjf<>xvLGj_ZoXUHy2R`3AMMX5l^UQU z58xwlD*mJ?a}AwyGX!o!?)NgG#gNmdx~ET{^x6Ud|FXgWCA;a18|^v#4qo3PCm84R zOJzYT97pnofGjofTD{bAqRIgETt~$je@|kgwbyd4gXPAe^)jJh?G@akW6^}yk1#>s zo%lh3BF=hPjwV_5ywi$J_7Uq61CAr&-DgzYdDG16x{Vw3CyR1^l!fEf{`TCiB@e#c z(#`2Gh^wg+MyNWSe}jwY?lr!_J@!*36LkP`Pj|p_ua#v6R2ra1S5jLzpsCks4oGf@ z%S2s>*=deg?e%U)WNs8t4`9(r4k+_l#{tC#)CVYDRA%oq{Ny!3%~hS)Bnu}398OjV zJdCW8PA9A4Ov6fzP%(Vc-Np2}*Xa%91VC=NOf&%KdZUZj*VXAoKT0o=wqnTq~Vr}2~rtsjV08IeXz)05pB!dH5In#z9_bz-wjGzRF4 zZJBu2>u29ty-WNoKm~bmW7oPnd#$3Ov=~v@U1xRO+2J9;a?!N~PE$6HVFi z-_Ma5=2jZef{3o%l{rTB z?=@|pa|YYmPjahFv}8wj-g8u!6Euel#jVQRCZH7&Enl%WY*H4y?(`m7ApKpj0jB`` zNoS=Ryo=6C`V>VDkX0cIr?MkHiy~LdV-&gcIEoyi)QHyXNbTzS)Dyf;b$x2?uQJgF zU=AI+isdJ-QR>~5)CmJlBVs9uP_8c_5z=NPg7%gF8y1*PiJ`WM}n8GrqG5X<9Cw9nKDuMDw?zO6&Xk7i%?ep!k zdL>3^pt*Lgn;r)3@!^JQPf|U8mx<~CS8}NO;hVhPiRv9M12oW7^mV{)uhse)khfD7 zG|pVp!+>~77q^jeH;Rc$BUI`GpLHfidL54fB>#{J4K%Oa#)-Ou4`f zG(qp-m5aNm9tNn-KjoIVTZ?|4&+@6qzNfFfzLK>|CUk)<{&JJ@pq-y9Qy*VyfCie2 zS$zMu4g%0j`cGNVK(mv@LuGQ%%6c2B4X1h-aD?jruiifodL6}9hx)NwCN$98Uf~*i z&{n_L=QXMfP_lcjcfC%~=_lDMG(~%4L0!c$G%@8!eXoBEwUyk&Uh99=_@3Z-1ZBxf zUSAt#Q{a-lGNFNH2us$wo>^WO(XQoN{3SpG&3P1{iY4gBTn1g=Vgac&sT@XXta=eQ zT$Kck+s098_Q+%2KG{+$JnCgvwDr9vj&$q5257`t^q>P)c)jxoH-oN{1$8^u-Qj>+ zy`FZs0hxab(14TZB!K+SwhcUjLyaglLL*L2duL*b*Huvivi8e_29O%3I^Za;U(_<7 z)Bue*YZ&fSi#B*ob3pC^Sq5LGT{T^u=r0QzagOjgP}l2GE+%I&w+DIsegyLtjHZ86B==n54c1u z_gd--tik||I2&=;RIPsXI>Y5e{u{EO5vSP=4ru4Kr^|^d12o_a!BLZiF>$|fgDcUZ zfilsKnAd2d>JR#Qt$%76&Tee80F5|_K_X9w_&;2Q5(C-;?B^DzdXD-$Q7656p1YHMf){8}?R;TOGhP^$vp_LE^}>;T#P ze)ln@ptWn;ec;IgL>3!)F65ru9O*TlvgLSNeg7?>S;IIcdLHO&o60DH*i`L^Jbk!* z6=8|Rsw>woEhScFu?={xkLBha7C618eXXJYaGjhdPDa=UY_2wRdnn~8_}VN14UfzA zd=6k<{gtA1Pssf^pu!H2N3fgM7V0sT9U(ridYPV3AEUsb>d5T}pRYakH$BF=6Ra>k zTFdNjFkaRIUo}GKkIKZU?d=4^-qZjv zF^prLd@MJowIfpfF#AyK7YZC=>3}UaR&D8Q3Y2B#J;we3dph&~5u;>EgS39|dA7q^ zCp@C19y=F$I4p9 zKX|U~kXv&xS%@!HpdFE;$wHR#Rx6-es{G3#9J~TXXt(I7ElMrYe%HRaaISHD3D63OAM1s zbj2Cgg>Nxzb;SNKar}UBq;}xj{(u~9MCBr-Fgv6P%+`*`nRTrRd>ycI!{jH`6$N>nKePS<#x?;6?Lk1M9y&)b*Tci ze2+=llun2XPXpiDM&5I5hvDN-w9atEL}F9nar(@Rv7m>y&|LTkAd47Hmd9ZIce|H>oOz_ zn;k zkxBGO^nME!sFg-6Kj;#p<<9*?4g+j4dLTJW_tBA-2P??sQ?S%8$tN z)^fEGmGc-+S*p2htU!Ar*SbMyUEnH=lMmUG&$KYMWy}zEJPnnco~VHGDqkDXGr%6$ zZXcIeVc1lfKlOQAz^V*86YP&mt>z4ysqsJZB=wklojcQ;E7C^vEV!fBT0g&5J0g1+ z4p@EK7qG-EVe%w9Qd7vR@!ApTOHE+`V7>x}rW0#FvarN>`IQNl1Q?XIup>?vNHSaU zoaSr}(ADH5 zOW-QQx>03F;I9fCl0mEzm^oMMg<|bVyx3^%h-{_vr0Fi0YwZuN*tm<}ey0c-9?FdS zmb_tf=$+3&sbE>!h+YgtReURxz=GH%G}9tT0&JqP=t;Db^!5XtpiM1_;#m7+jF*k6&=W?_Wy$Y_? zqxKhIXKP0!w|1GnXtUffj$UmWcsu3BUk$&Td%o1VJ;qnkM7d8fbb-vmkFyQ3kUJA)L%{6^zQZ>4e9!d=8z7NIUK6!wk7rYVpLmefY{I?{#rYh z*%`P*SUTOLHlkg@QYljW&)M1$`JIcR^c5@Aj>wbLDAiBHFjr|tKrw?oOcP zCd;idgFhm{TJ0jPU9aQiVgEPb`85IWKOQ2bt3dx>~6{5#e z&w1!!v;ukrbAoLUov)4PeH`#7Nm20{|1(KxmlFF)frH7eGWLGhv9S23!#@27HO}55eEp%(<$@_oaE_ZyZn{uFi4L=Q@%Gn4^v8!yIrEb(Hd(tsRlasiLRT zCn-?V^-@?bH~10Y$DcM|YmdPloUb*uST@1(v=Mz2ES0$f&8|>8A~R`D#Kt!UuF|;2 z;Kq?yrjrA{5VxAdHpLxPK<1L#h&~Qh|1tY^;3~sXIqTVUxB<)jQrHt42 z@(9BScOqvgpetV(w=FKc*baCSehtGI&9lr7Xv{E1dG}ta12}z_Hlj~~eM`-ulbfm? zk%_c=vb4~!40_(cmm2>x{0eFVXWU`@NNNKOZ}6%(M;~HYit*f4GX4y3O^h=Z7idT1 zX{u#gmd6x0)U{F&_zL5nCGhfQ=NEh>{yQ8Y(mYWCm1@2=qR)Xnh8IiDt}tvngM|G5 zAB`hv+rj}=cEIx-@D<%U^V4Bp%kDAstGFd|6_DK`ZA4!H`)1seZ&cF_OMr08h;3oSZ~fs8UGw&NxEOQ{f~Z;N(BVpIsSZeWR0 zf!Q2wL|+Dbk;M~AWVUuhZavRFxL9tnuMqnSYbLa>Jr=wDEPLW3?;GWR^i`sl;91eX z7Jj3HTMVy|O}red$M*h4O`mXrCdVqYir zcOK@VI7VwnWCF>eEQ>9+r{*7brdqo%v*=2mC&44mTC0P#HeCC5dl`GGc0^imV*002 zi_IW*ANRsE$+6gn&an27`<;&MMQr+Ri!IQONcNc)TVb)iiG7(1uFLvg#yUkGAex1Z zdJx4BW7 z#kMAvt|DuLjvcBp?o8w5;HlaZ`JC+H;8KeoM(i%`h0_FgSnOH~f^~!3jXHQZv1P;_ zPe-90kvYUN&8@K55ybwIZbNd$CdJ-EqN#`Z3Pj%|b^{JDU)hhXu;>fO5H7#UqO*w3 z$2X-p4J+5dP1;-iC{iFglGwp3tQoGg*cv37IcMT0#f~C&@m@>xc$r9?X-NeY5%D!14%#O|hIk{^34c96@Dyq|UK zSYl&K%|R~Ijz}qqro*bV*m1-j$#Rg^^0p|pmbUe}ZabNMXc3AWb@`Da8cbg7=m)Ode-P}++B1Ii6Gb=210Caj*N(_Lq>53x#A2rqTkjsbh%FYIfn};k&UPI;mDt<3X+d3^z1`M7 zlBZi+E4S$Ph+coGjXHa@Ba%UGk*vHOI(Qnf=g=imbnGl*Pv*q(2ecz{FDIruEw$L$#72pg3v03G5K9-3TdDdVeV^#8&Q^#8 z?7`)sm?*>w1)_6^9dnjV=Q4IFb`=G2E=8u=&#o_zfFzl8aHXrO;>{6vTt7N#=JjQUoyF<{m-d$e|5I35 zRkFJnz7U=oK2*?101F2?qYH1O8pQx!M!`m=jE- z6u9yN?TB=y6fWdVa0QgT-`fV+TVebX_}3{8+F-_h@v|xA7_WjWAbw)pwm2YP8_}g4 z(3g4Sanxr!Ai*s&>e5dN9AXI~cdCpng553Z$k}gS8R;1gzUn zt|v1r%T1AYDR4+UooMq;GsXfhBk&Q9;^9TJ$Q>}e z_rU`^pQk<1&j`H&Pem%!j>rIb>d|-qA75$w=kWcz*&JX%AMw-UHyGBd@00l$M@f|44o9g%g^=W|%8QQ&{-QL*t~!ry4U zL_Ahz2mC-g<$&IOIY8;i(nfS8+{x-DsL%;Cr8J*SEv? z*C{?O@6CQPTZ=AN8_}=8UUJnqUZ6dZI=&tor+RD~*sZVwzUF|Az8?1%|D>hA;F9sX09g$r)H+V@)6i{0zG3;Bg?cELAV%WU6;|2~C zmqBl1!YKl+X5cVSD@Y|(2v@> zhlzr2tD#9N^S|K`weMY9R;?yf&_@X~rCp)OdXF~H9dj0sy%sFcT*!_3BLt{M|9FYk z-SFNob=qp7Es2yEAjjfp=6!Y07G5`f#u^vnf6kjSQJt8jPpIj#0^{`;l+L%@0CoQR z&Q_{eZ9d28v_&@7=4Hu3goxG@v%sLYPBW*h(ttyVxP9jadu=pm{Cak9p~;alp&aP$ zFEZ$sm1ZJylmO-Gd9S%|Q3M?~-`47i4Tu8N{>0_LnO<*38DX=su@F5J;AEc7)8Z#P z@c-H|5kHH))U8q>_WsDPmuV2h5xd;!^k?iOxuXH>1-5BlxRWgKx&>A4Qpqa>*()Sx zeC1wKN%wmAC~GnKV+1H8Z`b;#E^6VKPB(C#M)XZas5qZ&=ANnz+TsMgbP_8XD-%Zp zthvcOsQ0_qCPQqZoERtI7=Yf)n`CK(*Zgd2)g=bRRo*i{a5;M7Jf}CVuyc&h!9?x( zKC-!wywF9KE7G1N`>~ZRlkd@v$hvvfv(=*GH2TpCmKvs#n`Av3{k7Mpsq$)^ zhULCHvPZkR@v0n^yWdywuFjx(c)UNPrPq;@U9Q-n`4fbx*^j_ORD#BO9hR%Ld;LgA zm0^byIGJcAsI}K;!CXS(a77bk?g--JPwN>DzGmU|TJoqNVKbM=6{f1W{0V1nmDdqm z{=w@i5oYf={f1Yrv+nkKB5#tjPLnf9fa+%h{V6jQ8XKnhWCkAcmm+jKxm+8KRa0MN zpw)#w$Lk!@KN@LPrr+IjIU;W|U?Wx77aw-Og6Eumdk~}%R~n|q`xUQKsM^HCMyFY- zFZwY!Ca1{U@dRd)|0<851vGkB(izN7rwXf0bh~F30&?p>_zJl?6F&1 ztUx;s-;A-dJwzj`(9Rb1+41`e?v2Ty&F83*>8H|SBuwFI@~4A0((VR6Z-O=^Z(KD1 zs}h!`y4Y`@>pFs7#I+r~W?pj41GGo3x<03ij;+;>!*Ae9nsPKh_9bTMq^gQt?sV3I z4&h?XG>ns$7^d=hjYq}RK!V-~c0s^$W-4uI1UJTSa2dVPYcmS2g>gD7Q~J?`X1*`18G+Q8?lSzNtLXl89>a?% z{JBh3WiDugcJ37@!%7WnN%RTyC(7lZg^k^thKA+N#hSf~bqATJW*)TPc6noNGaOq@!@0qT~{RR0R64-Gc|qsjo~Tkn>x1qOZdEA!NfKEQ%K z^3?Y_w^X7Xk$%-SRO?K&nitmz)Upoy+r4ESv`?n3B9zP%&=#QddFP%49m+i}JcXPO z1+)X08+TPHXp%6iPUQxuu6&LgroJTT^b!`iFp*av6YYsPbeDVkC1?Q?LZ%9p2B=-H zNp&wQ2klzj9xX`DmjyM0;itLF2wHo%d7+sL1jvqhawNzWc=kZ~Up-S4kB^9Sh;s5FV2- z)~(9r-^ET_7+}?3RLuz4FgOIGo>S>C<(*qG|Kob1Su8v#`;T`a4pP3{g(zFg5dVQe z8+OhU;=ZUQdFfVpMAs$;C!ye*=iQ&d>x9P-+}Bzd;HG5NIz||af-^eY3VjMWgo4^H z>xDkbvtWQ5PX#rMa4Liin_O4_QaKy9Nzp}` z#9$l@&ROTa8yC7*H-c62h4_-U7~(WooQq3Hj`&&1U#*g#No)~=(;@Vm=N2nNl;8L; zn)qMzjJFx#3>b{i^V1mR1F&52aAp#N@i3@49qSK{$d8az@^!aMu4>+4h%-@eM72BH zj8$H{M83+JS4)GlU{E{89flU=UeC!_HX6j>Y#1zhi~SX=c;yM3qlqV>PrS9AKc4TJ_9`*7p!IPF~qqr7!H9a-csdxFu*g8HZeF4 z!b@7aFRZq!rIuCiFXInCO@ze_TD`}WySQpb>bQ^dVX$eHJ5l@(`{0V=Z7}Zr)X|{N z1t|CkCn}D0h z`!AKtppp-1Fd1$W&T!+~c-N0I<+X^x6c|kU(#C)wWxl4K1{Wj5hv&G_^`-LRFhHlv`zXe$N$@&GKV*a#idY&V@BiXI$pVQi2UG3(FTUdf$%&QD>SH9{?}~zb;@Qj zxD3M6*ShoY2IX6ELjfJ4Y$GFF4ui~%ZXJ*r(v4f%BqwcRF%1?+oaat=#_O?w>KE{y zXh4Vrq@;=)y{5zR?mu0FzE_@s-=4Y%Ym-lCa0Lw3UGK*Fhsw(^GYv%7p+TtEm9QvA z{<+90RUWc*bK(!^HJ>uXRS+J~+YV1EPhKQHVA>=GGhna+Gb($Z@tG^+G*R*yBU}xk z0YjXp3F9+*%OiusTEyZSC^umR!3oFsLaZS0*rTG+?|mRH)S8PVVn-t*&V=1*m=hS$ zc+MdbvF39c{1-yB-JNQU%bs#SzWD_W{s)6sbTwwYxy=2tix|v;!F{+6<1WAl%EoJ* zxGwXGHu-B04E6~%Z(^wHVDTDG>ukUANcT!bSrZMehp_ktcRY>P4RsG-#oz`QymGkf z+3zYJbLuyISETAoMwkPG!)m!0!TLb?xW}--IT{E0D_YzL&65(Wc0VWS}eX;z4NWs^Pa5Dtz#v=sBm+|IBa+dyt1_|i6En;~qEZ)RL8+)B`ZKgaJt@wtaZi6r*=sK10 z^B1|Lg&54^6M}9y3v*}2SD;tn_GQgxhPWNV<$7gn{BVDH7M=Gk4eo%!v$)xCAS0aR zcn-Q5?(#H<0UKDa1~;ogfioy-mc?@z79)S-jZwTisk~o-+{0>yh5Mr_hu_GDwrG!X zw7Z)Qw$R{C2;U#;E`Ae_b9@b^B;31f6N3dXxCAF*o}+G4KJy-4>V>?j?-(KiB^%2O zu1C&QUXv@!%E(q4EQGKCW4rTSd=FOgcmtr02J-UBS2yxv!i%z?(;BEay%fagemC3# zxO8Twji=xOCxnOVO=6J?p)<~#Je z$!;IUZP*9a=M_IN!Xg-ax4{j0(kDY^d?m&Y(dI7DHH$w=CF<<&R_hapU6iqKSogK=TtqBye`% zhWrJUyC%E8_PRp37FSL0;}tlu zJ5rvWSG6-j2@F0S?ru2Tpf?_lp5?A%|DeGWFxZZ()DS1Nhp_k|PjMD?wCM9B3jT-R zEaEBAxc{@R2g^dU;7^)81$o`s&dj*t88gETmL{6Xdofr3#YLpo%7RX}^^g@zsAMPQ zrxE4C-6B`Api>ECEFW9=LH@SNKfecm4tgo(*NP4rJOlSdce=4-T!A|zxXSGigEAOw zxzb&8?_tbcnYelP>@I}h-Sir6$e&bs8b5--VP<@xwA!A21`mNrM+5^u%Pz5oA0A1{ff9 zV(=1#ht764*3DA@ER&VM}JafAF6?$z^TwGbityoQ3o8{B1& zamLNOxW$>8cMdzmtO_45#~|jlukp1wwI7PlGEAPj3(@3-Vs6OaU#b1c*@NB1^AT{s zcrj$boMVgEwK&8Q1*Gu<Cj#TA+@-_v zd$}__gs9?%{I!*RZgV}_ICR_+nfM}$Xz>sBSkyU+lP(%QV`xOivKCNZsr>5Ido@(9)VSuFGr zwB$adq_Y~N{2#Dc zl{~~?U17C!u(Ntbxdv=jEn>xsfSe#uhPx-M(Huj{f6V!>6xx0oIG z-HR`V0Vb=WWemX?_*C2+2dt|!Otoy_sMT{L z$*Esey*zDj@U49gXn%)hU*X~9`~FeGg13h<4~r!>^@}AI1Ji+lKuh0PVmUAe7!7n} z#S*K52rv%l0@U}3B^CgafZjm#&{$##FasC@v>p;mtN`W$V}Jlq(>s=!3ycR+frf)) zp~S+2V~JCNETH+ISYjzK69@ury<&-#z&s!uNCIjzV~Kgd1Rxz~>={ce0&;-10cHa^ zuJ{10ogzjQ2Qe?089YV zfyN(P8jHX=Kz|_iJ+c7I21WtxF=PP<17m??pl&O&089ijfu`?}1ziwpo$fh?f88W{j)R^#{wvC;M>G62j2vVkO^_6=kJm;j^$jjtmE zKn~C!h*cp2z-(X?(Eb`S0EB_DKr&GGDlz~}1Tul9SC9c1afFVHZL&yLy7Z?KsfSL!90bo3k z3N#cT1He=u3ut}-$G;T+n+XJgwx!4bFb~KEl7QMJ$N(?_NCz78kpUnF=nupeBLl!} zU=+}PKQaJ>fw4d`PrvH;8l#sC4J<}PFb7!RZZ4GWP4U@DNcFoZNj&=G){ zKoDqKfGhy>fNUTMsJ#u52OMOHz5PSR3Mav|25x;3;;8MAka1k835)1*+3Fddjm26OaRh> z#_N#*AP49V#I8dIfZ4z(pnWzn0EB_DKr&D_3mE_=0+~S5|8V?^|A!0!1A&(RA_Kr2 zU^LJ%6Bz&^z&M}_P=75l089dU1JP@c0bm9&1Zce)835)2V}JlqGXog_#sjH9!&S%t zF!d@Nmn>{FUx^F=Gl3w`b_Fs3%mcE4B%pRWG5|~f(t*Zl$N-Q7^ao;>BLl!}U=+}P z88QHbfw4d`P?v)Y026^spfQ9Y(R3*~0x%sI2((;+EC6$W(Ll$=$N~@n#sOV``l-kQ zFbU`lL@z=XfEmCLpmhqe0L%r(00E$8GO_@S2U3BCNjUz6_}^3@3uwL&Spa4NL7?pd z)DRV{1kVGqfh3^zd}IQc0Hgzr6OjoZ2j~yP&O;`E*}y2E{aj=M2m@n*WT5UGWa1ng z|B2Yh1ezuw3&3<>AkcC)vH;8hMgtvZAqzkR7zcC#>d!I~fYvjR z1z;{P1_%H(ry~o%cp&xk5YliOIs-5j$O4+jAq&7vAPBUbioO8M1G0f6p!O7G0GI%z z1C1vm13(VYABc@b27uYXD4_i$WB>>QV}WF#?mx&t2>+W1WCBedG5|~mnD&9-mTY7J zm;;OkI!;6ufCw-S=mONAfGhx$fZjm#cw_;X0Sp0J#~=&9Twn|k0BZh?EC8YL_+Ki} za2&D#Oa-!l=3|isU?va*+D0P_z&s!uNCImAg)9IQfOMeo7-Rv+0r~^6qmcz*HZTfc zquNIy6F?XkI||1?85?y+Ar-(xAQNaBiA(@=m<}EYw2VL|fH}Zupd*M(01;pu&;_U; zj!XcPfZjlK7%~CO0EPgqLy-w!E-(fN3=JU_Ly!t!Jdg@B9EnT-Q-Lg?c`z~o%mjh} zE7dj#*#I~!=Yg|qcj(-LIHy0QK1b~`DkPTowkP0;PMmB({Ko-z^FtP#61cE@@LC6F!56A|RfZATj z05Aba2O2Yx0U!tH55#&R1HkN_IR2xs(cS|Y0K&jnAQ`C3Kn8$`KqksYhe8i?&jwQ zN4Uojp|9_Kj#rs^BX*xd-2K**@DdR}2NL($Hz7Hx(|-8s;cxyoUN9px zNZ-q`XFiYVTSMh|fWh0SueP|*V{prppO3~H6Xc8V=`c0c@TQQ%t`Vk58%hUBi;5&2EL0zuBgXWpA!JJEenrl)>> z51)BUybA)819+f9z6?7cUkm1K-X74&gZ!`m6Fg#{%I(Yj&L;)?h1#~`He&EJM_u$#a9e5?5eDGA)#>Kez%(h+;acxh-4OO<~41M-nhg`C%3vjr| zzn<*)wig|DN^;x_ukTz*gI7Dbg30=VL1Tscd?wyPp}r5Eosj2$<9H(O3A1gxaqE{H z!yR7oE2ud6Nj%vm55v#RlauE9sbhn4_i1Qf?k^e}>>nz_QRSnf<6uC3OIzHAK>U1) zzG8JF-aq8$eLi*kjP{1x&v!?^3KeE%mLW6b7myip9-c;$uSX`x522;x`<#C$@B`iq zVG7&ujwJan2;`Y?AX|?ej*9T}jR?pTAB^5WEUDVCY(Kss96>;KtH-fp@&RZG`9=La3pM8Fd1|**%U{8>G#-j&_)I50Mjo-X};q9E3F(yDWHJCxh|lxzGNcj<@PT>2|)G6AnMu@mN%h2d5eXi~Jj& zPLkVHPr_TG{QRZ*4OM-p>a);mlBdF;3k-Smw!n}_ZC16LL~c=jahp4uC$4to``_Y@ z>U8LwOwPol#Rrc+pdsW*YutN2cld+H1y4?_4g1%P3m%!-dS?+{VUc5t=dug%Apzgb zT($7!igCfjgu|=uX32qg(!q^R42;JoZSsN5z-uGo1qD}MRuGlM53 zOn>WncMRI`6q?86G8{{$^!+}rQ=tM!;@DaVc(?vI^o;;zJJR(!8N_Mp&xJrjlvwyET<%}ieC6(|D4c9t;V3^adbLZT^zcDee_kS>% zJPNOn>G@?W1P+IT(A~*DPjUPfTEx$M^;&S)&(a+bgJf?&VYg2!pS1b@PXrAwyxH7u={(h+!xm8B!D z@OQ8@uY|U3ILWfK?IwTVg~5J3Ygw9dgm!nw-d835Wful}rAD5BIOsY(|K4_%fA59C zzNytxTCHd2Pbd4Yv9v=Dz!oP*R zB~PKS3tt<+zbw3cgbAXYW!)Y|OL#<$F$g}Ukc?HM8n*EB;Kgg)XkEONx}P{Xcvx!j(=4n-Z1$4cHU80) zgZ;WUv2@T;XS&fK?2nid%h`StLXHv>)qeCJcsQ6H945sGZ4tdDMdmdfp#8CD^ZPZW%+KfbqqbK2Gp2nG!s#YmF2x z`NX};w#3gzVQTnUx?lf-%f|ID`0JVlP>4Yr-i-s&-rg& zgvQ52?168iFqL-;d%K@w*zSj9$ssQ(r~ln}*OGg7?7dpPw@Fk?PS+@oy&cY^cdA4w zTEi$;;6)flaqKUXHExe!|5Za4(>6a1}DkOjNl(*}ayfgJ$48MIOaPWdE#7gNJsHR8Sa` z=6Zy%AA*otO=0jZ#9>=@t?}Ps^bRq+P{6+p zmZ8E|P?i~$U$?=Pi+=TezdVg=sAC-?=E5np(%tgJxj#FflV;@W|>)2cTIwQff zh#Q^Mw1OXcY*$nAdD?u0!rE(Z+g7ptQ*Dh=8!;_-W3RAf{4i)Ojw27*TK|E|g8edM zEF9eaqg%kNYH?gX%>V1M;6YtW-lVz!GZDXWw!q(U8D^rW6kd#6a;mua1%J@x=p{wf zH2n~rj2ZsWpK>{J*(imV;dNH}m-~4vELcm+M(vJ`{u?OFu4iH91FyJsgfaUo{vkoX zP~WSUi3<716s?{!K<~ttNnAPVSkbJEG*W-Vt)Y&yH~St&_}p# z=I9pohhBn_*&)I<%pp9zZ@bdpiomIrHH@)FhufMpe&%$vxlKxkV)o|wXQ+SLbfl;J zEt>uUQ%(`Ttnuf;G_^%aztaHUt?^f*G*tRFY*Q}MzJ8YUb?*%pcF$txO?JP%fU}vK z0-GsyE4$eBbz_`67rp~wuk;l2^Ps^v$+CII6R;gf%IceaOW$OCdHHbv>??u?q&A7| zPr8Ws=_dc0E70P?T1I#my@ki~-E;iqENzg|jVP75=p4U}rTOpDwnY~*Eob?=SXw8g zg}RU_oZ=6=5~aEC(RQ@fZ1ffWr7W$H(w$m|oj3XUEDgU;+Z@b?tV7ODe=SR^SUPwl zE^PRs;mB(L*DG=EZWr5oFm-XP2>TyhfjPLMjzJdTjtPT2NcMZrfY2(!$Lrl%?JKhX z9EGwE=rIIqS9%;n7LUZ(2mTjV1&61Wd?+E$ap##~ll@*Zf_=M3rSx`8iR|pfWOo)Q z`iSON;mV8sSy;{jT^mK1hSLL&(lq~>8Nq(t3hH4!cqdlU>_1aCMg7Mn1rO@EU-*~z zu*Rqt^;YyF*6r3ce%GtfyYfEf93eg_6T83V8`101b{J{6c+oUvG z){Wky4J-{~;m3^>{87D-%+&6$>v?aR+#>QW{Ad7szGJWS6ZrI8J-`(j^Ea8~VzZfY z_XfRbXdJj4*Q~{#LdrZ5LxpKHmU%S93p1}t3K*sEb_&ou2$#`|&|90=m# z@C(S9wP*m!ugpT7>BRBh?0YY%aU?@`@@v7Ci+anT||~lzCEtQM9Dy9xHn@)EBTT>gOR0> z%t_cFQ;Lc-R!fYj6n#aftB-OA!I(;;C_ms16QdYYDfpT`>qa@nm`c4Ut3vagv`U#$ zUX)G^>SRo%R+KumHKr2zhCYYf?V=e|sTO6fR@<0L2b9nOY3X6-WK5}YGsDftDw$^< z`0Cs9to%9o09U;@U}xAfV7*_4VgR|zdtQc|_2I`&GNQP@3nB<@<#-Z;>R{@zS2 zZ3G;6^evonlO-fl9`J5U!lK`vJ<) z)mJ1xh=u4@s_*Mk#yGoddH_E>SVysEHvY;dr!3>$coX;Q-KczS404alhC12!&%d_4 z`Ss6ufmqajXF9cCNH^O5+IHe6{|k8G@9De_?PF}?*4^6<{siyjSBd(4j#G_WS8q#x z5bKh5swwRYoaz|g8AV~nfjTW2YfD;x2+?I}q;xW@lXS$+vJg5y`(3gZOKvM+F>f0UDAGXIBvQ_tnk z-Qni1^1k@iL4Z!p;)J=ijT?Q`JTMhEZ@bIgV%fm`GIJ>Yg?oWRIXCt=%+|nf{c{IR zX5aF6dyV^+a)QM#{8i(Z{#u0Z1?|~EL<4_rJK*V!Eod-@W^VN1d5ixd8u)YDf!XK( zraLI+#vc1$@eK@qnPY!U-DI5n0~g2+n*L@tV}bjU`a{aJ3nZZ)g>8F>dj+#1tMaz; zzMWtfnH})fwiWqzTpv7i|E9Zmti7M{`N`{pLwjv^pG&tR%zk^!E4LT^}{s z2cG_Ch5U>gf+P3;ML+Kf`RCjaJmio!cffCC4%ZVnh++QMfzvP-1pA%qFM`Pl;oo6$ zs2$?BE^unSvg;CE#Z`*?KUh4Dlbm z5z|9K2W<8n(ETy%^H60dv&V%asQ=%r_S5vHDbp$dtGr!|Wd~z{#<>3fPMiSJ?ZCVplg?TE1}%B7dQ{$D6n! z!4J#g;#@W`J!vampnO=)Ak@&}9*qfu$F)#dLSn7iM$xiTM18)f)dRE=v)XVXxg@bLj@&L*C-;WR%@wp54 zj`^qVvD4AA$5U&l?&-7dVvnp(gR-^c7h3W9D}2}9!A58W|LrOms-n6lSkGfz_4_Kj zb5_9no>mOj&W$}&TQ}`+Bb2jH58j}0|6ERR5UTEmQ>Rz3F2(Sy;|Ja^Yv)F&(~&nz zaYZgZ9kjf+TUHvs_tcJr@I8zE^WkjFbz^qBnvVN|x{UIsa1unS_mw?))hXpl3M)A0A3 zWt1UC(IUo}Fv7(!P7Ac|v1k;FO=sa0#6GYIcT31=ft)=i1$hjz3r}IF7{daekXr1f zUM!NZSYvC9-`l$5f&K1TzTbyIOiA}K#-;kghw)w(A+J_UrsKW|LsAys5VYT z9=!5=N-OX+S2`Pu)FRTQnA|8CK1i>p@6!JFwANCz z8qwzIRgAGj3_nD-TwKjDqOnL-B7KC564t|5q;`?U;v4DArm;w&3ZD@RG@`L+ts-r` z%tbU7>DfYfrQsd~_Z2W^PGeNMzlJeE$ym}|@-U>H&uXR|OQ}X|EN8GVj!NLUe@z0X7rW8{i+GTv;X>ezeWQ97f=mE1`2&^4(#_C697Ep8L_EcJElEm}ceG`O4_ zDgAE6-9I{G1MIycGFsdsa)*X?>@6s!Gg@5Ajg%vE+>RZ4Z;FZ*H;ekB?%1)nQ&hCL z_%ZrUMjzmQC(oC}crURu0WEG4`8Q3qWA9f{(c;3DbiNj6P&zyIREdi-ummB@>+V_uybi;Nbxi#qxy=WHx0T3qoY zLw};7jYUO^TSa{hm1bmPQPJSCr|5e@NJC$sEHYXg6S+l08;gn-mz2`^$%QVov8ZTq zlxoJSnh#^DXmHWf6svc;7FCCIgDTqFDC%}hIjplWMKrfy6y=;L{ed2&JR8A)pMaSYrv$mQ0+DiXJ_ul zn4|PL3blB}iETFK0Hu&|J{DLwlZFDi!ElUMTu${`ES* zYv?)d3MU#u^sNrOi@`2>EMi>k{PE$%kXna_lsB9hHH&8;FoK z^5GQp7QD6Jzz<=xv8ebZ%W6?qU|~nqSk$iQPokcADSkJPGB?N~ zqj{C@GxXJX=bZO*j5`IYYyQF!Z4-63R?GN6Rtsu*9eocx)J5FGRB_x}sAep}LYMmk zyWb5HXY{xasK%za{Tg$>_<6f#5i7AYqpLAJAr^l~&j7AcrQ1IBT^O7siV-#9FWt&@Yehd%kIjh}h1@}oAH2xt46sQLu5nzi7JZrqFpeL)4$*&+gNqlAl;e8k7mWV| zmZI!DPlR+M?A`!C3){q?5Etugq4C2BnTa^K_(K`xn;0Mnof$Hwp1YNLi|8Y;nx((- z!wJdM5x=yF{)w1KnW2zv(7^ScW-)j|D`1?Ra92O*{V~?RWPn?Tx(XP_^(N6DL55fX z5mE&entP$t^uKdZUhiu<#n=y1~Hg{9dMOt9M|)|W`GgeM~txp`eO%mqMxl9 zFplfFQTm@Q6+r)Y8(949X<>~RT&EQP1h}K42W5;_|lA{~B$8aa^wzedu`@|4iXfJ(e)wM1(mq5@Uex&US~un7W%o zt3_X_88D9P9isnNGhiH#U->=bf6BKXnEFqZVW4wxn;0Ca88F67hBF0c!tx&&U?eKY z1{lZn7SV@JbBEA4u9yBu|Ik62LSq`Zxx85n7UsB4W*paxTNvO;O|fxYZxa1z&8#tW zo$3pJf`2G8OH*tdH)xt z%s6gP1A_xHSLrb}j_cu8>htv&8&h{DvntVF!!21JVq@rf2-{nE{gHX9UQZk2WRv8M zam6p(!6IBcvVz8Oy;bz5as5c$xL}We*{}2;t$oNCmp)p7*smcPtiX4#*ollIK{F`% zjru};JJ=X{f~#Ou^t-ybK4Ki#i`wXaJHGM63K~;)eXKDg1_N$z0gPDzXHc-60gl5r z02#nI5)2>aDo`(ay&hv@=>433-VXZTa;p2DhcW$~9;y|CyHG=R663f*j7~<~IKG48o%BBrhkz9@ zj(4&q(QnjFZmjWn|E;it0bbEwZXB;bgXkY?FE@@?Ab%JAN9jyw9Irr~=tpS=j2Zvj zaEMcB?rsLSSuSI3fY4hySAgAe~8#SpnC{szlG#3>ZuNkj&-nV$c`I zn4QcxUV)16qu4>SX26&ka64!f{W5K#aooRbKK-B21{zZjxd1UScwJj)9N$67oeXfF zPQ}LY7Dh#XLC*!oalL2({g2lQ8W*O9Lj&AY*(e6{wT8wpP`x0+04ubD#sz!ydeM*9 zlZ|mW)rMi-Lh;u_utK>oHDo)e6@wG?5E#cR5V?y15;4qph>YVEs206D0`oG~IPTve z`h{p9b>qU&o)%Qz%^lo`7Sg~tzJoT=2kF_)INrkYT>4+DDK?H*phfiOG{eTBxIyVX z4DgPo*f?H+X33;@VNZmNDSBZW#;>&#L4F?Vo*rr0>XgI3X(X^M^GdRadG zpVthN<^EH=0x>a|rz;}kcm+z9NB~_CJ+BVRK>Y6JeuzUU( zpQ{_iV5+WIjN_Nj1rIR5WPH(>7beC|?}w?lUi2Sv+07jo$NlpP=zpWezmeDf3>4mT z`CTgpD{xuP0LF1W@*o4O81C*H7{@Qat3^-7EYNbT*kuC`Ws!TW3NF4J?4#e&Fs6v-0PP}1u5zBn>RIt9!>*g_L~;tNrfTb>{!fqM&zqI4pw+v$NlVd~ zM!1U|6LCL0NuX$~Vo5PQ?>Nkf#wtcd?4+Wxibapnb2-CuN|Fsq_=lY~iu$d(8mm~a zlCB5fu^4M)tYW>0*Qlqlig}OI^Kfm8G561%){0uBuEr`xO6WRtf!nFEiq#_a#B~>I zWUOL`i2GjPL}L{zpLi6Pgc)CH?u}J#gL**56s@nZisesId`qiqtYV9Zr|V9QRV;mq zp8eIce@Hh}Z5H)a-KnvP#ievj?C%<5tYQ*NUf%O`ovu|fR@Yh)Khhc*s~CBKp2Ji$RL$vWyUHNzf4z84}`IbO(Gtt2f|pz!b*DX)B_xlm?92z+3R%Ohz#<&$ymjh zh-afl6pd9Zd4ry>qDB;r`ACj&qoSUODVwUXx)!}j*Iw#stYV{x&*@H$RV=8c=kMxi ztYSUIP`Bw=n6q;lV_wc%OSjjsN?~n`>4rg2E8=H(4VTvy#uVWhSx3*V7dz2d#cC1n zRnf8bKg8`2wMtcExS|0^h&3Yi(=-^X7=DkQ zp2jt%h#FOixP7WigRzS3B8Fybl8iNO#ruqVJa)>jP#CM&D&i+W_d6ZNDwfsJ^N2s( zSJsUwqDChXm6p^E%59v8ct81)cqli;X}?!XN){~<}$ zqP~H+Op>vR9U{i`m>R2Cxq)$~X^xC3B1df^KBuCx8~;$tH`28P(7ka)zw&Cn?7OOEm|XEbuIi9V%n*_-HmW# zp1T{UWE_A~1n=D$j5=}P%px_O_STZn#F@(x*80t!NYUb1!LYoNZ;eHsqmt(XaO8I8E zWIUxwHHHzz77@p3QjJwC{g$4$X;O_mV>)nAgR7uQ(D28wAraZikSF=j*ZzoRk&*OWZOj(Pkc)lteg8VO)(jIl{EcPqsUhC0z$ z#TpS`#u}BL#wvzm^jxE1ja96o7|NJ|1klx3)pn}sCt~TwW*B3khKq-a@2QQ|j%SR4 z2d!1KQ?0)9Nb7(1;|w9qBm9gUq>@Dm*myUqnQ#tu-?dTJSqwQCq7K95!2&lKlsmorwe zR>UvWQ`n7vagA)F>w(&Oc z^a||XZE!zQjq+cpo}sXeC|^+(8U@Wxh*QpWka+{1rk49>%_a47kcew(&C zb7Q(iMfn;(?!$=2REl=er%%A0_l>DEiZTPclKUUrkn=C3f(|+j(6gN}o$9G%+=dB) zJ2KY#koCAHKtN0%ESQvlrEjHAxtTEA)Pv*MO2Kb)QIwdR?e78_%8aqu9Y*U zQYFd?oQ)aHm`b}Sp_9>{*!PSnRou;Rov+~c@{u}aDy^a%j-Q2N7L2Ks<anFhnhAC!K>HWq~qW3V`2u$}>jOkN!FO~kf>@ud(D9W!oM2$Ie3Kr34 zhYnF=8B-yVMxol=kujybJUZR3L(`Z_EtQM`7*5QoF*Z5#MDC-Qh0#ROSjB3JX}{{= zCd>MhK|4hHMOS0SY**#|bQ*>``;2HzrA?H4EU2g$Qz>5zpKhx$|4}i<{MSMutxyMM z;mz7>=~J3d=?3JFKPhBPrCF23TpNDl|8dGT!Wv32IV=9G9>9Y|>1JUq< z)^0Y#ovSrK$0>)J8L^&Q^l9P}zmD~dQtkv;iOr=JY$1z^y`kNbU z8Kv-pbmCWam^ouARic#WXf~$OF3K*=k1>^shZyYyZICgQR#Aq8^y+PhGNm$~PANLb zjH$##xmm**QzIrql@OfV6itFUC{~mQh)w z6N)jFdQnz+Zp<1}$y-jJ&O2O|jj7azL>i%OHKr6PqEm^s)tE}PDEu-h50NpI4pBbA z%7mlYm`dd%h?X%%$E>kEe`*u;7#+062*D9u{wOPwi#xnrwiq*LizxLt|8br)<{G(l z1%3X6!k@k}rqV3RNL(MV@*_jKL8-WyPAQsNV=7IeEYyK+%qkQ<2A^(^>p(ZgKyRRs zcBc+>W4h$8q%zHo^H4xHr1RH_bcS|hV>;zNPN%E!q?@D6m`aT(w_-)bA!JM?Ttc6E zok5MMREhEqM!t+cZrJ#17isrj?j25JI#oQuaD#OUFs9Nf$_yQu##G9lq|bNSAY&>q zQGN*Nu7B983MEg`X^{3jV>(4exn8SaOr@xlJ}+TLXU{XH(kM!T_Hbh=1y9TPJ56_F zOsO6c`j76&m`dI%D*wZ+3+~96O06ipbVtTiBG1t0e%+5TmFkd4=j&K9rqn?t{jp2k zj*PRg9L8uWW57$VcA7E0+Nh*Y)yrRF=T-hJw2Tot1|945ABI_rs7LA;G)5aa21{3S zhbxD>F=)&kHjA=O$Dpy?U3`u{bvQS1bQ)7>66J1Ym;09u?g&z0Ii0@Jfon{qL6kd@ zM0QnUD*0>Z(}O|S7-`+E(lKVV;I*0W<(^X!gX>%63Rk|_L(=N(9Rg9@rR4`a*r5-9{OdYMFENF8VLdFovUW7}=5*3Vb z;m3F}ifOmvmu)#s8dE8GiOMo{Go})KDMaaUm5jL_Dtehp^bpr1V=9fJ{Dn7tcpJ%> zN@kd1FkmcGu2FQ6KodHv%y0s(|6TKW-3ZKLnFkB4q<6l=7?T^ut{)nlblNMFqh;B;Fm_s5e z${{#AQ!%De^frA$=jxp!V`j5aq^TFV+16M_*gJGOTEiJrsTbv9jb_YfdA0OOzS2cA zrcZ6{iV&o8bPZ%or^vf>nu_HMS|2c`Q?)3wC%U#8)2Bm}n`S!2m`de)j5Z8YD*LE0 z`&+1uQpPFTIgGhe_?5p8G5yVXE}}8+exM#L)Vhs;Mq}eF46iy0@8S&2of$)D7NHQg zt0*`g8Q`P2;t$}GG8{h(#@9d{d+S)p-|uPS#-Mz>D9o{(?{9sZf7{_hx;%@Coo6@4 z-m5H>Ul9;>2wtM3>e$<1YW_#`eHgx6%sKX+XCZy-L=BF2UBqQD$@!_xL_kg;sBI!BjrQ<8a=HXdmo7kvzVv@@Mm#&@Em)&4R9Hq zjM*4x9|kL7K}rXf52#4MvG*20eF{JH*fVY3~O64J-PDE`@lI#K4ZdH&{rQ zMs5uLVT9|OyGHm0@JTKBl%@4&yV9S|cBS=FIu8Syv%td_`ESFvd){ZT?Q{?ZCVr8j zm>+uh_3s8VyVr^^3)z6s6c<8~Mi`}Bhr9c%kz?;k7V`Hms=1MV`Qz@}QO4m!_V6#o zGck~y$rBWToOH0TXBp1^91t%nV-q4eV)5q;jHXs{qv!2&^ybJ?^aHko|HQD#4BNOd z@Rls6FUazLdJli>sr(C;emB6CwhoZet}QGba1;JO1~1VT`s3dZ_UT@_iG}y*$*h3v zPk29gaB4G!ftP8vZy(`5{eCcOT5%If({8@eHQ-KV*8NQ?oyTQL73C66On<{A9IL)d znWj6b?8{-poD_bEPlum}wFq-^$x;50y5J#4H?TBq{1MLk0%fj@w^P|ClR3`+imngo z#PirF{|>mO)=B9KZPKc%{bv|3_iNauysiD@TVd~U7IwxLg#rN_CPb`Z!GKG3&3moC zt1j3lH5_H()i{H(hI4ZKAs=9ahuuYeaCoL=<08_@}79*->nF_fVDKtSf#!9 zMP+B`wNT`4BU`bNGU-y+j%mW)(=4P~&5ev-XE=42GGm}?Y%!}2ZX7%o=P;SML%PAf z8>TJ(@2!k6BsMC!k&=o$@E9K^>@`Rsre`~3*`u)9W?_#FuwaV6R1PF&2ePpDhree) z)Uli!8D%=uULJ+_NNCT07{d)_*20Y*8QR^ml*J6umi(a6O1W|HRBghH|6fx+6k9Z< znHwpI$Sj-EQ`igt7-H$(Z9yfAe`MkL`oJhh*n5kGY(kT$AI@?u{ao0a-=bZaMx8ib#=ACdt zk@Ug5jLJX5*Gb`*IJ0n?bU#tzZDU~q@|gQG@1vv~d$E%pd#g|?r==Qhq@0MaDRB|v z*!xaYq#?YG>VEjjF7r8K6WLqILMEw7)NZO?@6@kMZ5Q=ms=SVy=j3Ir>RiE%lzI5_ z4lmFgd!LGmvt_HO75HN_YQMTKun)QGBN{IrdC@2_-* zT*8f%i?Pt;Y1*;(wy9B3J7c25SP3}x?)*)Ci@1?85`B=qj=eWT#nEXLb!V3Ib?p6# zLj1HQ#_+52i+T zNdNx?JLZb^80;9GtYinAxdg*p&S6>2&ncxa;*`-DM*Pb;EM(m~MEzMqob5ss{jMQ& z#Zt-7DM#XnGsImk#3mHFpB8Nsd9&`}BqtZNyBOKdf43xd>^;T8eX{wRW-oCw zF%gqOjadG9o0}&cds|q@gWW1FS)89j;oXesMVzH$?=cqAvWy%1h-H-+zJT99V0ImQ z--#ir)-LL|^{$bQy_J744Acs4q@0PrXwA96vG)lJL!B{~%0HO3irHFChGTC@xESjr zc4Gd6RT&FXQqV^@Mjd+}h}B-PVq*0@D#Tqn_U@Sv*8?q905h`R`gt&^X9>$w=4nXB z-s|)I5u1WNhebvF9ly)K{W|2zfsENbw#UR z^jUB~YQX}QUOL~+E|<>tH?XvxrNK|JL}mO>ulAE0g9B6ZA}HmyLte>^eyecXhw`dP{)o@9<2EU6)N3Cw_i#|^-LyRsSGcqV%YMBU z7N;Dkv#4WlQ7#HyKV8O6>8GXKO8E#UOa^f5y_@StKM$s7H;ec#?gvqH>@B*v(avbEo@< zpt*UBxk{Vl*n2Ebx@)LL#0&J8IQF)%aPL7BzK@B$;zWZed4r47b-LB+k#;V}P@F^Gyycx5R>?iaZanM1*bFqjDB*CPWCc!e? z2;*2SyVXCm2_v9vF-xm3T3A{&-@kyRF_sRStKq(B_3v*A4(MKzkJ2MgM=77)uP6I! zcc5G2%!SHCDF{sl_ zR9uh*!zBIap>=zu!Ckvt`p`xz}S;;UxlrA z>^;lEy$@q83pzcEOA`F1bt69{U;!5?VCi}+-?4Tm;D-eKz+knM9)>q5a2LE@N@w9O zPjpCeDMG+F??D>lR8q-}PJ?m9592oZkcuTVOv)dk@?TuSLuru@N8`p9e#$q`r*n3| zTP_>OS}8Y%M|2{HEcEAp6+EI(GfOiL!UY_c5yng*Tq1@3h_8b^`V<$^s4uRLXk@HL z)oRovMo;6;FO7`VsKXhB3Li$Kv_+@{JD_owu>tQzD&50@KsHA#I1uIr{+y-PAWrXK znaCxTaTm1z7g1=u#|hhkaTx2%SmpBuxD|$RXRS{8GHKYsb+qa>8U2d~);NMce6j4I zXs~x`?sDkClk}lW{q6pcXmDWH8kUau7q0W^^)G)~G&ndlT*ShUapB6AeO>K85)BUO zUL~a!lU-8YBm2csoM_r9jJya>%bBg)r}uEzd?0Q%TE7H~mX&y5jxWAVd-B<$yG2_EWS z{B1BfHE$)=pYTYTC-IJ*{*B)T2X(Dw=~26)ZV|T2fA-tpkkrWIEZpmM~u?}A5kZ;;a4|F5?z4UXbCqpOj`S%g&-E`eYX0%Q(r#u!(i5~HP3 z1?9xHC}QJ+RKR88nB)&frQ$<)7jZfs+X7@-#==NI0yZ}YmQx52_ZSPK1Tdt$LMkH& zhX4V>;mCX4)3ZWQ`H_QFHQnEP@B4a=o}TWWWyf9Llm)upF@5{v6 z@643!QljxK7}Sx1MQ^Ct^a?k})^hgZ!*<9|77p0=F{e3Sa7$u~RHD;4v$wxoqOm0@ zkxewblG@k;l$cF)heTtmO`;TNa)U%4SX<&%knS&8#UQc8B+;+d?A@VGqD@zhnu$B- z%#K_|^|9HmS`F7;v4tbCu-5F_=`>N^qH0;NUUbjsm}kVXS~S;XYlt?-#D;xDJJIqy zuKB10$771jt8n6UDfJhwW&GIElgK%b_(zD!TObQhEy1vePHUbQm(H7=gmd0Z^5?Gu zmF6u+%_No5y^N^WFI3RVjJW5ooVgf#0Y}7MPa?xzO&ajD_|*j*)`LXN*iw|3e*vv_ z#s+F*D^KDGwPi%j*g}&q{$XZ>?htL$!`*XB=D~Rz0k#gyw#hbuYh?u?`~rOj8f$P1 zjW%KT$k;Lu9(~xU#&zmPr+OOQo2+1AO(cxtgnzv2z!xkkff9$LpPCEPYWLt0m3&mg zvt1#jSt>;ETUtB|7o|^NlxpRD-8?~76tp)nyz;^Cqkc-0PAgdGzSP~TwQe5A*xWvu z%VSYVA%BhEhux~7krqE&RW+Eo*jZ(Ecqwl)2=Bxe(Mp>1OEo9aIsCVg;7Dj63$0W& z2#pOoL&O?}n;<8X+04c0OJ=XO1rZXPF_q?MeWyshWcF!WDZvBywgJ}+z7{VN%-cfc z?09t_{YZQS(C-i&@Lm`7AZ}h4apns8;W=B0j={POYa1UBLoNd?m*{%Tj)-pSrO@y; zY6rQ$vp=+tLU%~?Sqz7$9cGC-Mre@eA@q_&zkWfXCEFR{=kAR9r5WPNRkLq$okZ*1 z2+f~@j|g5xlU}uh@^A1Afk94vI<;Ly!xgh_ za#T`p;b{RKRx=lGTtocAQu=hoNQQ)!Dn6(~{F4%Wv%5my@2=4NUDT#zD71fuLMtR1 zb-!SCp{sZnJLI>^sJ+rt_5HVdiayt{EjzI-{)3YGEtXArv&eZu9s&Q1-E>%)snF6) zg_cS5kLXq8jpccU>Fd8E(Sev;5gqc1_zlr5dl+E==2Ap|`l=`*S})OmPEx3UvN%n2 z-Ck;wFomJEa}Lq;4q@C4QgIPU(sobLf*E4Ob-1i3hl{lbQ*IuqJ@vxAjxkRSQF9a? z`V$>>TkN}z+jY@CqDh#D6HO9#C_N*={utbFkkZ9Nv(yIE=I84QRqpDZp~Hb)?9_= zABEPO;vR`9uZp@`xIii-nv1D0BjipN;~Ie4Ur{^M-Rq$_3Oy*%8q6iAt(hqbpfzSz zh&>JF9}ICUGU&G1qIK)YIXH6~wf|h?7YWwwR`Cb!7K!0)t%J?PeNdN0d%sl|3eKBW ztaKGD;Oz=<$;)L?j%X@aEb5AiZaj4nW63e3ry!5z7L` zLVUKwW*1}CG(IfdQI@xfxpPo3xZM>janfkNhe9HE7F9Z)fwxB3f6~kk!FWb8nD;e< zXCsbhv;$*nrahRDXLSJefu`^l3&%6?stfx=&7^?wjLu*_(hOd~>39Y%a63;kUBP%p zH!yQG6TtueaXhO#sCk-71LGMzz|7Z7IvCIB2_|1Ncw@8U8NI=L45kH-9NrauA0+L> zMA%P&TmU0e9@jpgXi1|lC;`JyKQ3j^_YVGrNQftst@bH)0eRk{IsYVoSMden*OLFF zF+T;GyK&P06Y-(s7dGYZDSn|S1s}3M)x71#cX{G+XutzfNKpa=J@iJXAQI=sXEuD$zmnp*ok`|bUc8E0)Snl72Gr` zJb?95QLGiLmkJLENB}Cq3RXjf2LxQjpS6N9 z*wHJ1kJ1ycmQ1h*sG}su}#p25{VGt3CA-n zdrjjY02~jX;s;Qy)e1&MAK`cagR;|Drxn~8Dm)+nAVkS}E#bDZZ}9*|1z>N`3Pz>E z0~nQxjatDN=#m@{U<~$AC0fB4R1gRya(~%>Y$8oF0*M?JPXN1_278I$fuRw{ z6BQxK0Z$*G(nx~AzHJK`8tBv=&p=miZ>2Lj^deaZ^#m_V=&z%)z}vt!ihvZ!0^A&p zL}h`O)^=9W4po3Iq7lbfjnSw?8E;2pEe+mv92D@D95+N%!VJ7qi*XGU(cq-QVWAzh z>;w5hQ8pCRYL{x4x1p2;JWc9dP_&Y0{2qy?fgc{P-5>^Z zg>lFo930A#L%EPcCan<6BBald79;%x!$J1?I`6jt>mPfdj6<)tiiH5%uIkdzbl$CD zgYk7mo`S?2OS{w!2#>2aI>OFHJ_CvEh95e}_p1yaUv0dC#5~Ivz#s1V`Fr8pfp1*# z`#R!J!KAZ%n2MD&qBTXrr7Isnhv7*&8&lsH9r7Y)xjZW`k5wLvPIvwVOB&JKJ}qH% zcvt>=x}NkfwPyie3l%fVCpL7l1{vl1#HCKw)Mn-TA-WZrm|_Kuw*2i=rI#ge#BfR8#IwTRU; zT?E!NbwszWQ%DysuCF$lraCw`P4&QNcB+^RB!lV){p9X`ccF-BZ>N?c2`dJm2gki#X4F;HlbfWAfI@nqRI zRB*_|4@OIM1j3ynBYRjGts_G-t>$q;nAXVn{QBa^CDS_Fw#U8sOE4qmJMb3eqm&T7 zAHoozl;!yQe9K%#zPOfUy=?6LIPzT3O7I&;H;L>K*6`*VH$!uGNM!K{>uxtpic4?m zNXJ>aVMa11TYv8$3MX09IOa#EJw#@{=q}_e@51-s)vjpSf{sjcQm*fBd -- 2.54.0 From 1f1bee62e854ec9c75e8b49072d0c403c7f0a100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Anic=CC=81?= Date: Fri, 24 Jul 2026 14:06:01 +0200 Subject: [PATCH 064/215] Io.Uring: context switch depends on struct layout During context switch in Io.Uring `fiber.contextSwitch` functions leaves `*fiber.Switch` (contexts field from SwitchMessage) in the `rpi` register. ```Zig inline fn contextSwitch(message: *const SwitchMessage) *const SwitchMessage { return @fieldParentPtr("contexts", Io.fiber.contextSwitch(&message.contexts)); } ``` ```asm .x86_64 => asm volatile ( \\ movq 0(%%rsi), %%rax \\ movq 8(%%rsi), %%rcx \\ leaq 0f(%%rip), %%rdx \\ movq %%rsp, 0(%%rax) \\ movq %%rbp, 8(%%rax) \\ movq %%rdx, 16(%%rax) \\ movq 0(%%rcx), %%rsp \\ movq 8(%%rcx), %%rbp \\ jmpq *16(%%rcx) \\0: : [received_message] "={rsi}" (-> *const Switch), : [message_to_send] "{rsi}" (s), ``` That becomes second argument to the `AscynClosure.call` but there it is interpreted as `*SwitchMessage` which works because both points to the same address (contexts is first field). ```Zig fn call( closure: *AsyncClosure, message: *const SwitchMessage, ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn { ``` SwitchMessage is not packed or external struct allowing reorder, padding. Reordering fields breaks expectation that `*fiber.Switch` and `*SwitchMessage` are the same pointers. --- lib/std/Io/Uring.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig index 59d932311384d4e3de96ef51d618e61338e4783c..58d97dc0e8e090c84bec204f74be93a8bd5e5c37 100644 --- a/lib/std/Io/Uring.zig +++ b/lib/std/Io/Uring.zig @@ -1135,8 +1135,9 @@ fn mainIdleEntry() callconv(.naked) void { fn mainIdle( ev: *Evented, - message: *const SwitchMessage, + contexts: *const Io.fiber.Switch, ) callconv(.withStackAlign(.c, @max(@alignOf(Thread), @alignOf(Io.fiber.Context)))) noreturn { + const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); message.handle(ev); ev.idle(&ev.threads.allocated[0]); ev.yield(@ptrCast(&ev.main_fiber_buffer), .nothing); @@ -1414,8 +1415,9 @@ const AsyncClosure = struct { fn call( closure: *AsyncClosure, - message: *const SwitchMessage, + contexts: *const Io.fiber.Switch, ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn { + const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); const ev = closure.evented; const fiber = closure.fiber; message.handle(ev); @@ -1779,8 +1781,9 @@ const Group = struct { fn call( closure: *Group.AsyncClosure, - message: *const SwitchMessage, + contexts: *const Io.fiber.Switch, ) callconv(.withStackAlign(.c, @alignOf(Group.AsyncClosure))) noreturn { + const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); const ev = closure.evented; const fiber = closure.fiber; message.handle(ev); -- 2.54.0 From 8e6aa0a7ec968be26b451da95fd88398833904e7 Mon Sep 17 00:00:00 2001 From: Mark Rushakoff Date: Sun, 25 Jan 2026 22:33:49 -0500 Subject: [PATCH 065/215] cli: address TODO to remove formatted-panics and structured-cfg flags These flags were supposed to be removed after 0.15.0 was tagged, and that happened about five months ago. non-structured-cfg is also no longer supported by SPIR-V backend. --- src/Compilation.zig | 3 --- src/Module.zig | 17 ----------------- src/libs/freebsd.zig | 1 - src/libs/glibc.zig | 1 - src/libs/libcxx.zig | 2 -- src/libs/libtsan.zig | 1 - src/libs/musl.zig | 1 - src/libs/netbsd.zig | 1 - src/libs/openbsd.zig | 1 - src/main.zig | 14 -------------- 10 files changed, 42 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index df6fc7b06b192553ca5faed923c4a9b4406814f5..80ca20d7d37475606c0b957a07f2b30b42bda533 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1232,7 +1232,6 @@ pub const cache_helpers = struct { hh.add(mod.sanitize_thread); hh.add(mod.fuzz); hh.add(mod.unwind_tables); - hh.add(mod.structured_cfg); hh.add(mod.no_builtin); hh.addListOfBytes(mod.cc_argv); } @@ -7270,7 +7269,6 @@ fn buildOutputFromZig( .unwind_tables = comp.root_mod.unwind_tables, .pic = comp.root_mod.pic, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, .no_builtin = true, .code_model = comp.root_mod.code_model, .error_tracing = false, @@ -7419,7 +7417,6 @@ pub fn build_crt_file( // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC. .pic = options.pic orelse comp.root_mod.pic, .optimize_mode = comp.compilerRtOptMode(), - .structured_cfg = comp.root_mod.structured_cfg, // Some libcs (e.g. musl) are opinionated about -fno-builtin. .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin, .code_model = comp.root_mod.code_model, diff --git a/src/Module.zig b/src/Module.zig index d245c0cf02f15bb7ed695dcac2914285c9debfb6..0567c07a6021f74c13a04c8ff74c6cd509d83633 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -42,8 +42,6 @@ sanitize_thread: bool, fuzz: bool, unwind_tables: std.lang.UnwindTables, cc_argv: []const []const u8, -/// (SPIR-V) whether to generate a structured control flow graph or not -structured_cfg: bool, no_builtin: bool, pub const Deps = std.array_hash_map.String(*Module); @@ -85,7 +83,6 @@ pub const CreateOptions = struct { sanitize_c: ?std.zig.SanitizeC = null, sanitize_thread: ?bool = null, fuzz: ?bool = null, - structured_cfg: ?bool = null, no_builtin: ?bool = null, }; }; @@ -320,17 +317,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { break :sp target_util.default_stack_protector_buffer_size; }; - const structured_cfg = b: { - if (options.inherited.structured_cfg) |x| break :b x; - if (options.parent) |p| break :b p.structured_cfg; - // We always want a structured control flow in shaders. This option is - // only relevant for OpenCL kernels. - break :b switch (target.os.tag) { - .opencl => false, - else => true, - }; - }; - const no_builtin = b: { if (options.inherited.no_builtin) |x| break :b x; if (options.parent) |p| break :b p.no_builtin; @@ -411,7 +397,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { .fuzz = fuzz, .unwind_tables = unwind_tables, .cc_argv = options.cc_argv, - .structured_cfg = structured_cfg, .no_builtin = no_builtin, }; return mod; @@ -450,7 +435,6 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M .fuzz = undefined, .unwind_tables = undefined, .cc_argv = undefined, - .structured_cfg = undefined, .no_builtin = undefined, }; return mod; @@ -489,7 +473,6 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories) .stack_protector = 0, .red_zone = false, .sanitize_c = .off, - .structured_cfg = false, .no_builtin = false, }; return new; diff --git a/src/libs/freebsd.zig b/src/libs/freebsd.zig index fd8e80a78f6931227bd5e1ed7a21366c0cbc775b..0895ef4280ed25592fbcfda9fa54960675d28271 100644 --- a/src/libs/freebsd.zig +++ b/src/libs/freebsd.zig @@ -1077,7 +1077,6 @@ fn buildSharedLib( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = &.{}, diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index a23757c2f6107cf8b2f48b732d5505563127a9d5..59abb61f333a8baf6ce54a485ff3dcdbdefd2afc 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -1223,7 +1223,6 @@ fn buildSharedLib( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = &.{}, diff --git a/src/libs/libcxx.zig b/src/libs/libcxx.zig index 4036cec8f6447425bd9c7e8eaba5c60e2b33a17c..88a92274188ff5294bf7c868027f49d3c9e5d40c 100644 --- a/src/libs/libcxx.zig +++ b/src/libs/libcxx.zig @@ -172,7 +172,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, .pic = if (target_util.supports_fpic(target)) true else null, .code_model = comp.root_mod.code_model, }, @@ -366,7 +365,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, .unwind_tables = unwind_tables, .pic = if (target_util.supports_fpic(target)) true else null, .code_model = comp.root_mod.code_model, diff --git a/src/libs/libtsan.zig b/src/libs/libtsan.zig index cb15557c5b57c441217568e67caae602ddfa37a9..2621391c769f63c678ab419c0bc8db7c95f2326e 100644 --- a/src/libs/libtsan.zig +++ b/src/libs/libtsan.zig @@ -100,7 +100,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo .valgrind = false, .unwind_tables = unwind_tables, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, .pic = true, .no_builtin = true, .code_model = comp.root_mod.code_model, diff --git a/src/libs/musl.zig b/src/libs/musl.zig index 3d32cc98b722252c029489076ea1ef7c9132cc6c..eca461940ce84ad1aa8d26dd406b6c4c3100dbb3 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -225,7 +225,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = cc_argv, diff --git a/src/libs/netbsd.zig b/src/libs/netbsd.zig index 3b7162363f148c5332dd721923ef8ff046faa46d..fb811df536ed7fa55f2ec630534e1c995ef978f7 100644 --- a/src/libs/netbsd.zig +++ b/src/libs/netbsd.zig @@ -727,7 +727,6 @@ fn buildSharedLib( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = &.{}, diff --git a/src/libs/openbsd.zig b/src/libs/openbsd.zig index 7f6dc2db817ff630366f463a9405821714a12c95..e38183ab75db6a29eae22695f52550f69b35858c 100644 --- a/src/libs/openbsd.zig +++ b/src/libs/openbsd.zig @@ -647,7 +647,6 @@ fn buildSharedLib( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = &.{}, diff --git a/src/main.zig b/src/main.zig index a7b8ddb6d08cac1dfd2b882f4dda65ec03c181d1..7a69c9ba65d5c1da8f687f2cb2a6d7ab7eb28698 100644 --- a/src/main.zig +++ b/src/main.zig @@ -557,10 +557,6 @@ const usage_build_generic = \\ -fno-function-sections All functions go into same section \\ -fdata-sections Places each data in a separate section \\ -fno-data-sections All data go into same section - \\ -fformatted-panics Enable formatted safety panics - \\ -fno-formatted-panics Disable formatted safety panics - \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow - \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow \\ -mexec-model=[value] (WASI) Execution model \\ -municode (Windows) Use wmain/wWinMain as entry point \\ --time-report Send timing diagnostics to '--listen' clients @@ -1200,10 +1196,6 @@ fn buildOutputType( if (mem.eql(u8, next_arg, "--")) break; try extra_rcflags.append(arena, next_arg); } - } else if (mem.eql(u8, arg, "-fstructured-cfg")) { - mod_opts.structured_cfg = true; - } else if (mem.eql(u8, arg, "-fno-structured-cfg")) { - mod_opts.structured_cfg = false; } else if (mem.eql(u8, arg, "--color")) { const next_arg = args_iter.next() orelse { fatal("expected [auto|on|off] after --color", .{}); @@ -1650,12 +1642,6 @@ fn buildOutputType( create_module.opts.debug_format = .{ .dwarf = .@"32" }; } else if (mem.eql(u8, arg, "-gdwarf64")) { create_module.opts.debug_format = .{ .dwarf = .@"64" }; - } else if (mem.eql(u8, arg, "-fformatted-panics")) { - // Remove this after 0.15.0 is tagged. - warn("-fformatted-panics is deprecated and does nothing", .{}); - } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { - // Remove this after 0.15.0 is tagged. - warn("-fno-formatted-panics is deprecated and does nothing", .{}); } else if (mem.eql(u8, arg, "-fsingle-threaded")) { mod_opts.single_threaded = true; } else if (mem.eql(u8, arg, "-fno-single-threaded")) { -- 2.54.0 From 4e5ce9909a7a008ca6a4a4fb9c45c473f95c9a8c Mon Sep 17 00:00:00 2001 From: K4 Date: Wed, 22 Jul 2026 19:07:53 +0300 Subject: [PATCH 066/215] std: add test for `ArrayList(u0).toOwnedSlice()` Closes https://github.com/ziglang/zig/issues/22483 --- lib/std/array_list.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index 1c665f3bdb892db15a3de341dc55d4194fb3db2b..edece7882eaa79caf502cd493833e902b064856d 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -2366,6 +2366,10 @@ test "Managed(u0)" { count += 1; } try testing.expectEqual(count, 3); + + const ownedSlice = try list.toOwnedSlice(); + defer a.free(ownedSlice); + try testing.expectEqualSlices(u0, ownedSlice, &.{ 0, 0, 0 }); } test "Managed(?u32).pop()" { -- 2.54.0 From de5c25420b05aab47346a7cd4c8d9def85b9d0f9 Mon Sep 17 00:00:00 2001 From: nyx-xyn Date: Tue, 28 Jul 2026 21:01:34 +0200 Subject: [PATCH 067/215] std.unicode: add peekCodepoint (#31038) Adds peekCodepoint() to Utf8Iterator and Wtf8Iterator. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31038 Reviewed-by: Ryan Liptak --- lib/std/unicode.zig | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index 259e46d685bcfc00fc118e8b4cd95f47bdb3869f..a6cd094800cc0a77fcd84394bc08736df7352b0f 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -425,6 +425,15 @@ pub const Utf8Iterator = struct { return it.bytes[original_i..end_ix]; } + + /// Look ahead at the next codepoint without advancing the iterator. + /// If no codepoints exist, then returns null. + pub fn peekCodepoint(it: *Utf8Iterator) ?u21 { + const original_i = it.i; + defer it.i = original_i; + + return it.nextCodepoint(); + } }; pub fn utf16IsHighSurrogate(c: u16) bool { @@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void { test "utf8 iterator peeking" { try comptime testUtf8Peeking(); try testUtf8Peeking(); + + comptime try testUtf8PeekCodepoint(); + try testUtf8PeekCodepoint(); } fn testUtf8Peeking() !void { @@ -790,6 +802,20 @@ fn testUtf8Peeking() !void { try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1))); } +fn testUtf8PeekCodepoint() !void { + const s = Utf8View.initComptime("東京市"); + var it = s.iterator(); + + try testing.expect(it.peekCodepoint().? == 0x6771); + try testing.expect(it.peekCodepoint().? == 0x6771); + _ = it.nextCodepoint(); + try testing.expect(it.peekCodepoint().? == 0x4eac); + _ = it.nextCodepoint(); + try testing.expect(it.peekCodepoint().? == 0x5e02); + _ = it.nextCodepoint(); + try testing.expect(it.peekCodepoint() == null); +} + fn testError(bytes: []const u8, expected_err: anyerror) !void { try testing.expectError(expected_err, testDecode(bytes)); } @@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct { return it.bytes[original_i..end_ix]; } + + /// Look ahead at the next codepoint without advancing the iterator. + /// If no codepoints exist, then returns null. + pub fn peekCodepoint(it: *Wtf8Iterator) ?u21 { + const original_i = it.i; + defer it.i = original_i; + + return it.nextCodepoint(); + } }; pub fn wtf16LeToWtf8ArrayList(result: *std.array_list.Managed(u8), utf16le: []const u16) Allocator.Error!void { -- 2.54.0 From e045b77d9981434af7e87512f94ecfe5b9dc376f Mon Sep 17 00:00:00 2001 From: Pavel Verigo Date: Sun, 26 Jul 2026 22:01:41 +0200 Subject: [PATCH 068/215] stage2-wasm: linker emit obj + fixes/hacks --- src/Compilation.zig | 8 +- src/codegen.zig | 31 +- src/codegen/wasm/CodeGen.zig | 5 +- src/codegen/wasm/Emit.zig | 170 ++- src/codegen/wasm/Mir.zig | 52 +- src/link/Wasm.zig | 1116 ++++++++++++--- src/link/Wasm/Flush.zig | 1245 +++++++++++++++-- src/link/Wasm/Object.zig | 2 +- src/target.zig | 2 +- test/behavior/basic.zig | 1 - ...n_functions_returning_void_or_noreturn.zig | 1 - test/behavior/call.zig | 1 - test/behavior/export_builtin.zig | 15 - test/behavior/fn.zig | 1 - test/tests.zig | 1 - 15 files changed, 2177 insertions(+), 474 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 80ca20d7d37475606c0b957a07f2b30b42bda533..6561f88312664801ea4dc1d217ecf85ae413c1af 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3675,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values())); addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind))); addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index))); - addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag))); - addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset))); + addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.tag))); + addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.offset))); // TODO handle the union safety field - //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee))); - addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend))); + //addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.pointee))); + addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.addend))); addBuf(&bufs, @ptrCast(wasm.uav_fixups.items)); addBuf(&bufs, @ptrCast(wasm.nav_fixups.items)); addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items)); diff --git a/src/codegen.zig b/src/codegen.zig index 4ad10d48c05c59608f06956209f7f9b66a6d2775..326a9f1e2f52b90bb40bf4006000c3864a47fed5 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -767,11 +767,9 @@ fn lowerNavRef( offset: u64, ) (Error || std.Io.Writer.Error)!void { const zcu = pt.zcu; - const gpa = zcu.gpa; const ip = &zcu.intern_pool; const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); - const is_obj = lf.comp.config.output_mode == .Obj; const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type); if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { @@ -786,34 +784,7 @@ fn lowerNavRef( dev.check(link.File.Tag.wasm.devFeature()); const wasm = lf.cast(.wasm).?; assert(reloc_parent == .none); - if (nav_ty.zigTypeTag(zcu) == .@"fn") { - const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); - if (!gop.found_existing) gop.value_ptr.* = {}; - if (is_obj) { - @panic("TODO add out_reloc for this"); - } else { - try wasm.func_table_fixups.append(gpa, .{ - .table_index = @fromBackingInt(@intCast(gop.index)), - .offset = @intCast(w.end), - }); - } - } else { - if (is_obj) { - try wasm.out_relocs.append(gpa, .{ - .offset = @intCast(w.end), - .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, - .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, - .addend = @intCast(offset), - }); - } else { - try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); - wasm.nav_fixups.appendAssumeCapacity(.{ - .navs_exe_index = try wasm.refNavExe(nav_index), - .offset = @intCast(w.end), - .addend = @intCast(offset), - }); - } - } + try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset)); try w.splatByteAll(0, ptr_width_bytes); return; }, diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 2848a5f2573c75c73036aa2ff19f583403a9085f..8d6e18385f8de67b92f5ba72cde959fc6df83b91 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -4923,7 +4923,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; const offset: u64 = prev_offset + ptr.byte_offset; return switch (ptr.base_addr) { - .nav => |nav| return if (Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) + .nav => |nav| return if (ip.getNav(nav).getExtern(ip) != null or + Type.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } } else .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) }, @@ -5607,6 +5608,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass { } fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { + if (dest_ty.eql(src_ty)) return null; + const zcu = cg.pt.zcu; const src_class = cg.bitcastClass(src_ty); const dest_class = cg.bitcastClass(dest_ty); diff --git a/src/codegen/wasm/Emit.zig b/src/codegen/wasm/Emit.zig index ccc75b9b536871e5010f1a5155cdd0ae4abf9301..a83597dfc4fb3b0749a66fdf0c7e62c8995457c5 100644 --- a/src/codegen/wasm/Emit.zig +++ b/src/codegen/wasm/Emit.zig @@ -21,7 +21,7 @@ pub const Error = error{ OutOfMemory, }; -pub fn lowerToCode(emit: *Emit) Error!void { +pub fn lower(emit: *Emit) Error!void { const mir = &emit.mir; const code = emit.code; const wasm = emit.wasm; @@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void { const target = &comp.root_mod.resolved_target.result; const is_wasm32 = target.cpu.arch == .wasm32; + // Write the locals in the prologue of the function body. + try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38); + + writeUleb128(code, @as(u32, @intCast(mir.locals.len))); + + for (mir.locals) |local| { + writeUleb128(code, @as(u32, 1)); + code.appendAssumeCapacity(@backingInt(local)); + } + + // Stack management section of function prologue. + const stack_alignment = mir.prologue.flags.stack_alignment; + if (stack_alignment.toByteUnits()) |align_bytes| { + // load stack pointer + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_get)); + try appendStackPointerGlobalIndex(wasm, code, is_obj); + // store stack pointer so we can restore it when we return from the function + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee)); + writeUleb128(code, mir.prologue.sp_local); + // get the total stack size + const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size)); + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); + writeSleb128(code, aligned_stack); + // subtract it from the current stack pointer + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_sub)); + // Get negative stack alignment + const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1; + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); + writeSleb128(code, neg_stack_align); + // Bitwise-and the value to get the new stack pointer to ensure the + // pointers are aligned with the abi alignment. + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_and)); + // The bottom will be used to calculate all stack pointer offsets. + code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.local_tee)); + writeUleb128(code, mir.prologue.bottom_stack_local); + // 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(@backingInt(std.wasm.Opcode.global_set)); + try appendStackPointerGlobalIndex(wasm, code, is_obj); + } + const tags = mir.instructions.items(.tag); const datas = mir.instructions.items(.data); var inst: u32 = 0; @@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void { continue :loop tags[inst]; }, .func_ref => { - const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @fromBackingInt(@intCast( - wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?, - )); - code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); + try code.ensureUnusedCapacity(gpa, 11); + const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; + code.appendAssumeCapacity(@backingInt(opcode)); if (is_obj) { - @panic("TODO"); + try wasm.zcu_relocations.append(gpa, .{ + .offset = @intCast(code.items.len), + .pointee = .{ .function_nav = datas[inst].nav_index }, + .tag = if (is_wasm32) .table_index_sleb else .table_index_sleb64, + .addend = 0, + }); + appendSlebRelocPlaceholder(code, is_wasm32); } else { - writeSleb128(code, 1 + @backingInt(indirect_func_idx)); + const function_index = Wasm.OutputFunctionIndex.fromIpNav(wasm, datas[inst].nav_index); + const table_index = wasm.flush_buffer.indirect_function_table.getIndex(function_index).? + 1; + writeSleb128(code, table_index); } inst += 1; continue :loop tags[inst]; @@ -105,18 +153,17 @@ 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(@backingInt(opcode)); if (is_obj) { - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, - .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, + .pointee = .{ .data_resolution = .__zig_error_name_table }, + .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, .addend = 0, }); - code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); + appendSlebRelocPlaceholder(code, is_wasm32); inst += 1; continue :loop tags[inst]; @@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { try code.ensureUnusedCapacity(gpa, 6); code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); if (is_obj) { - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) }, + .pointee = .{ .function_nav = datas[inst].nav_index }, .tag = .function_index_leb, .addend = 0, }); - code.appendNTimesAssumeCapacity(0, 5); + appendUlebRelocPlaceholder(code); } else { appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index)); } @@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { ).?; if (is_obj) { code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect)); - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), .pointee = .{ .type_index = func_ty_index }, .tag = .type_index_leb, .addend = 0, }); - code.appendNTimesAssumeCapacity(0, 5); + appendUlebRelocPlaceholder(code); } else { const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse { // In this case we tried to call a function pointer for @@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { try code.ensureUnusedCapacity(gpa, 6); code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); if (is_obj) { - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.tagTableIndexSymbolIndex(datas[inst].ip_index) }, + .pointee = .{ .tag_function = datas[inst].ip_index }, .tag = .function_index_leb, .addend = 0, }); - code.appendNTimesAssumeCapacity(0, 5); + appendUlebRelocPlaceholder(code); } else { appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index)); } @@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void { const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; code.appendAssumeCapacity(@backingInt(opcode)); if (is_obj) { - @panic("TODO"); + try wasm.zcu_relocations.append(gpa, .{ + .offset = @intCast(code.items.len), + .pointee = .{ .data_resolution = .__zig_tag_name_table }, + .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, + .addend = @intCast(wasm.tagIndexTableOffset(datas[inst].ip_index)), + }); + appendSlebRelocPlaceholder(code, is_wasm32); } else { const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index); writeSleb128(code, addr); - - inst += 1; - continue :loop tags[inst]; } + + inst += 1; + continue :loop tags[inst]; }, .call_intrinsic => { @@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { try code.ensureUnusedCapacity(gpa, 6); code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); if (is_obj) { - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, + .pointee = .{ .function_name = symbol_name }, .tag = .function_index_leb, .addend = 0, }); - code.appendNTimesAssumeCapacity(0, 5); + appendUlebRelocPlaceholder(code); } else { appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name)); } @@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { .global_set_sp => { try code.ensureUnusedCapacity(gpa, 6); code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set)); - if (is_obj) { - try wasm.out_relocs.append(gpa, .{ - .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, - .tag = .global_index_leb, - .addend = 0, - }); - code.appendNTimesAssumeCapacity(0, 5); - } else { - const sp_global: Wasm.GlobalIndex = .stack_pointer; - writeUleb128(code, @backingInt(sp_global)); - } + try appendStackPointerGlobalIndex(wasm, code, is_obj); inst += 1; continue :loop tags[inst]; @@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: try code.ensureUnusedCapacity(gpa, 11); code.appendAssumeCapacity(@backingInt(opcode)); - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) }, - .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, + .pointee = .{ .data_uav = value }, + .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, .addend = offset, }); - code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); + appendSlebRelocPlaceholder(code, is_wasm32); } fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { @@ -995,13 +1037,13 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; code.appendAssumeCapacity(@backingInt(opcode)); if (is_obj) { - try wasm.out_relocs.append(gpa, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(code.items.len), - .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, - .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, + .pointee = .{ .data_nav = data.nav_index }, + .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, .addend = data.offset, }); - code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); + appendSlebRelocPlaceholder(code, is_wasm32); } else { const addr = wasm.navAddr(data.nav_index); writeSleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); @@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex) writeUleb128(code, @backingInt(i)); } +fn appendStackPointerGlobalIndex( + wasm: *Wasm, + code: *ArrayList(u8), + is_obj: bool, +) Error!void { + if (is_obj) { + try wasm.zcu_relocations.append(wasm.base.comp.gpa, .{ + .offset = @intCast(code.items.len), + .pointee = .stack_pointer, + .tag = .global_index_leb, + .addend = 0, + }); + appendUlebRelocPlaceholder(code); + } else { + const sp_global: Wasm.GlobalIndex = .stack_pointer; + writeUleb128(code, @backingInt(sp_global)); + } +} + +fn appendUlebRelocPlaceholder(code: *ArrayList(u8)) void { + code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 }); +} + +fn appendSlebRelocPlaceholder(code: *ArrayList(u8), is_wasm32: bool) void { + if (is_wasm32) { + code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 }); + } else { + code.appendSliceAssumeCapacity(&.{ + 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x00, + }); + } +} + fn writeUleb128(code: *ArrayList(u8), arg: anytype) void { var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); w.writeUleb128(arg) catch unreachable; diff --git a/src/codegen/wasm/Mir.zig b/src/codegen/wasm/Mir.zig index bbb41312990a836c336b6a3aa303ba2f0e363521..5f602496e901acc56864a8e45143fd7e14d193f7 100644 --- a/src/codegen/wasm/Mir.zig +++ b/src/codegen/wasm/Mir.zig @@ -114,7 +114,7 @@ pub const Inst = struct { /// /// Uses `payload` pointing to a `NavRefOff`. nav_ref_off, - /// Lowers to an i32_const which is the index of the function in the + /// Lowers to an iNN_const which is the index of the function in the /// table section. /// /// Uses `nav_index`. @@ -679,60 +679,12 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { } pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayList(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); - - var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); - - w.writeLeb128(@as(u32, @intCast(mir.locals.len))) catch unreachable; - - for (mir.locals) |local| { - w.writeLeb128(@as(u32, 1)) catch unreachable; - w.writeByte(@backingInt(local)) catch unreachable; - } - - // 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 - w.writeByte(@backingInt(std.wasm.Opcode.global_get)) catch unreachable; - w.writeUleb128(@backingInt(sp_global)) catch unreachable; - // store stack pointer so we can restore it when we return from the function - w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable; - w.writeUleb128(mir.prologue.sp_local) catch unreachable; - // get the total stack size - const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size)); - w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable; - w.writeSleb128(aligned_stack) catch unreachable; - // subtract it from the current stack pointer - w.writeByte(@backingInt(std.wasm.Opcode.i32_sub)) catch unreachable; - // Get negative stack alignment - const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1; - w.writeByte(@backingInt(std.wasm.Opcode.i32_const)) catch unreachable; - w.writeSleb128(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. - w.writeByte(@backingInt(std.wasm.Opcode.i32_and)) catch unreachable; - // The bottom will be used to calculate all stack pointer offsets. - w.writeByte(@backingInt(std.wasm.Opcode.local_tee)) catch unreachable; - w.writeUleb128(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. - w.writeByte(@backingInt(std.wasm.Opcode.global_set)) catch unreachable; - w.writeUleb128(@backingInt(sp_global)) catch unreachable; - } - - code.items.len += w.end; - var emit: Emit = .{ .mir = mir.*, .wasm = wasm, .code = code, }; - try emit.lowerToCode(); + try emit.lower(); } pub fn extraData(self: *const Mir, comptime T: type, index: usize) struct { data: T, end: usize } { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index a1445d3b4fbe49d94f43cb88cab30a237f4cd7cc..6ec027ad7f64991b38266e16ad04ee35d66ab14b 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -133,25 +133,21 @@ object_total_sections: u32 = 0, /// All comdat symbols from all objects concatenated. object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty, -/// Relocations to be emitted into an object file. Remains empty when not -/// emitting an object file. -out_relocs: std.MultiArrayList(OutReloc) = .empty, +/// Relocations produced by Zig code and data lowering. These retain semantic +/// targets until `flush`, where final output indexes are known. +zcu_relocations: std.MultiArrayList(ZcuRelocation) = .empty, /// List of locations within `string_bytes` that must be patched with the virtual /// memory address of a Uav during `flush`. -/// When emitting an object file, `out_relocs` is used instead. +/// When emitting an object file, `zcu_relocations` is used instead. uav_fixups: std.ArrayList(UavFixup) = .empty, /// List of locations within `string_bytes` that must be patched with the virtual /// memory address of a Nav during `flush`. -/// When emitting an object file, `out_relocs` is used instead. +/// When emitting an object file, `zcu_relocations` is used instead. /// No functions here only global variables. nav_fixups: std.ArrayList(NavFixup) = .empty, /// When a nav reference is a function pointer, this tracks the required function /// table entry index that needs to overwrite the code in the final output. func_table_fixups: std.ArrayList(FuncTableFixup) = .empty, -/// Symbols to be emitted into an object file. Remains empty when not emitting -/// an object file. -symbol_table: std.array_hash_map.Auto(String, void) = .empty, - /// When importing objects from the host environment, a name must be supplied. /// LLVM uses "env" by default when none is given. /// This value is passed to object files since wasm tooling conventions provides @@ -244,7 +240,9 @@ function_imports: std.array_hash_map.Auto(String, FunctionImportId) = .empty, /// remove elements from the table, and the remainder are either undefined /// symbol errors, or symbol table entries depending on the output mode. data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty, -/// Set of data symbols that will appear in the final binary. Used to populate +/// Set of data symbols that will appear in the final binary when outputting an object file. +datas: std.array_hash_map.Auto(ObjectDataImport.Resolution, void) = .empty, +/// Set of data segment symbols that will appear in the final binary. Used to populate /// `Flush.data_segments` before sorting. data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty, @@ -302,11 +300,6 @@ pub const TagNameOff = extern struct { len: u32, }; -/// Index into `Wasm.zcu_indirect_function_set`. -pub const ZcuIndirectFunctionSetIndex = enum(u32) { - _, -}; - pub const UavFixup = extern struct { uavs_exe_index: UavsExeIndex, /// Index into `string_bytes`. @@ -315,14 +308,14 @@ pub const UavFixup = extern struct { }; pub const NavFixup = extern struct { - navs_exe_index: NavsExeIndex, + nav_index: InternPool.Nav.Index, /// Index into `string_bytes`. offset: u32, addend: u32, }; pub const FuncTableFixup = extern struct { - table_index: ZcuIndirectFunctionSetIndex, + nav_index: InternPool.Nav.Index, /// Index into `string_bytes`. offset: u32, }; @@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) { pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex { if (wasm.object_function_imports.getPtr(name)) |import| { - return fromResolution(wasm, import.resolution); + if (import.resolution != .unresolved) { + return fromResolution(wasm, import.resolution); + } } if (wasm.function_exports.get(name)) |index| return index; if (wasm.hidden_function_exports.get(name)) |index| return index; @@ -374,7 +369,8 @@ pub const GlobalExport = extern struct { }; /// 0. Index into `Flush.function_imports` -/// 1. Index into `functions`. +/// 1. Index into `Flush.intrinsic_function_imports` +/// 2. Index into `functions`. /// /// Note that function_imports indexes are subject to swap removals during /// `flush`. @@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) { } pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex { - return @fromBackingInt(@intCast(wasm.flush_buffer.function_imports.entries.len + @backingInt(index))); + return @fromBackingInt(@intCast( + wasm.flush_buffer.function_imports.entries.len + + wasm.flush_buffer.intrinsic_function_imports.entries.len + + @backingInt(index), + )); } pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex { @@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) { pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex { if (wasm.flush_buffer.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); + if (wasm.flush_buffer.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast( + wasm.flush_buffer.function_imports.entries.len + i, + )); return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse { if (std.debug.runtime_safety) { std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)}); @@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) { } }; +// Order +// 0. Flush.data_imports +// 1. Wasm.datas +pub const OutputDataIndex = enum(u32) { + _, + + pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputDataIndex { + if (wasm.flush_buffer.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); + if (wasm.object_data_imports.getPtr(name)) |import| { + if (import.resolution != .unresolved) return fromResolution(wasm, import.resolution).?; + } + if (wasm.flush_buffer.data_exports.get(name)) |symbol| return fromResolution(wasm, symbol.resolution).?; + if (std.debug.runtime_safety) { + std.debug.panic("data index for symbol not found: {s}", .{name.slice(wasm)}); + } else unreachable; + } + + pub fn fromObjectData(wasm: *const Wasm, index: ObjectData.Index) OutputDataIndex { + return fromResolution(wasm, .fromObjectDataIndex(wasm, index)).?; + } + + pub fn fromResolution(wasm: *const Wasm, resolution: ObjectDataImport.Resolution) ?OutputDataIndex { + const i = wasm.datas.getIndex(resolution) orelse return null; + return @fromBackingInt(@intCast(wasm.flush_buffer.data_imports.entries.len + i)); + } + + pub fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) OutputDataIndex { + const comp = wasm.base.comp; + const resolution: ObjectDataImport.Resolution = if (comp.config.output_mode == .Obj) + .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)) }) + else + .pack(wasm, .{ .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)) }); + return fromResolution(wasm, resolution).?; + } + + pub fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputDataIndex { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + const nav = ip.getNav(nav_index); + if (nav.getExtern(ip)) |ext| { + return fromSymbolName(wasm, wasm.getExistingString(ext.name.toSlice(ip)).?); + } + const resolution: ObjectDataImport.Resolution = if (wasm.base.comp.config.output_mode == .Obj) + .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)) }) + else + .pack(wasm, .{ .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)) }); + return fromResolution(wasm, resolution).?; + } +}; + /// Index into `Wasm.globals`. pub const GlobalIndex = enum(u32) { _, @@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) { return .stack_pointer; } - pub fn ptr(index: GlobalIndex, f: *const Flush) *Wasm.GlobalImport.Resolution { - return &f.globals.items[@backingInt(index)]; + pub fn fromResolution(wasm: *const Wasm, resolution: GlobalImport.Resolution) ?GlobalIndex { + const i = wasm.globals.getIndex(resolution) orelse return null; + return @fromBackingInt(@intCast(wasm.flush_buffer.global_imports.entries.len + i)); } pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) ?GlobalIndex { - const i = wasm.globals.getIndex(.fromIpNav(wasm, nav_index)) orelse return null; - return @fromBackingInt(@intCast(i)); + return fromResolution(wasm, .fromIpNav(wasm, nav_index)); } pub fn fromObjectGlobal(wasm: *const Wasm, i: ObjectGlobalIndex) GlobalIndex { - return @fromBackingInt(@intCast(wasm.globals.getIndex(.fromObjectGlobal(wasm, i)).?)); + return fromResolution(wasm, .fromObjectGlobal(wasm, i)).?; } pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex { @@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) { } pub fn fromSymbolName(wasm: *const Wasm, name: String) GlobalIndex { + if (wasm.flush_buffer.global_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); const import = wasm.object_global_imports.getPtr(name).?; - return @fromBackingInt(@intCast(wasm.globals.getIndex(import.resolution).?)); + return fromResolution(wasm, import.resolution).?; } }; @@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) { pub const TableIndex = enum(u32) { _, - pub fn ptr(index: TableIndex, f: *const Flush) *Wasm.TableImport.Resolution { - return &f.tables.items[@backingInt(index)]; - } - pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex { return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?)); } @@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) { flags.ref_type = .funcref; } - pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { + pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool, is_obj: bool) bool { return flags.exported or (is_dynamic and !flags.visibility_hidden) or + (is_obj and flags.binding != .local) or (flags.no_strip and flags.must_link); } @@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) { /// Masks off the Zig-specific stuff. pub fn toAbiInteger(flags: SymbolFlags) u32 { var copy = flags; - copy.initZigSpecific(false, false); - return @bitCast(copy); + copy.initZigSpecific(false, flags.no_strip); + return @backingInt(copy); } }; @@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) { /// Used when emitting a relocatable object. pub const ZcuDataObj = extern struct { code: DataPayload, - relocs: OutReloc.Slice, + relocs: ZcuRelocation.Slice, }; /// Used when not emitting a relocatable object. @@ -855,7 +906,9 @@ const ZcuDataStarts = struct { var uavs_i = zds.uavs_i; while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { // Call to `lowerZcuData` here possibly creates more entries in these tables. - wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]); + const uav = wasm.uavs_obj.keys()[uavs_i]; + const zcu_data = try lowerZcuData(wasm, pt, uav); + wasm.uavs_obj.values()[uavs_i] = zcu_data; } } @@ -906,6 +959,51 @@ pub const ZcuFunc = union { return &wasm.zcu_funcs.values()[@backingInt(i)]; } + pub fn flags(i: @This(), wasm: *const Wasm) SymbolFlags { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + const ip_index = i.key(wasm).*; + switch (ip.indexToKey(ip_index)) { + .func => |func| { + const nav = ip.getNav(func.owner_nav); + if (nav.getExtern(ip)) |ext| { + const name_slice = ext.name.toSlice(ip); + const name_string = wasm.getExistingString(name_slice).?; + return .{ + .binding = switch (ext.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = switch (ext.visibility) { + .default => false, + .hidden => true, + .protected => false, + }, + .undefined = false, + .exported = wasm.missing_exports.contains(name_string), + .explicit_name = false, + .no_strip = false, + .tls = ext.is_threadlocal, + .absolute = false, + }; + } else { + return .{ + .binding = .local, + .tls = nav.resolved.?.@"threadlocal", + }; + } + }, + .enum_type => { + return .{ + .binding = .local, + }; + }, + else => unreachable, + } + } + pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 { const zcu = wasm.base.comp.zcu.?; const ip = &zcu.intern_pool; @@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct { return pack(wasm, .{ .object_function = object_function }); } + pub fn flags(r: Resolution, wasm: *Wasm) SymbolFlags { + return switch (unpack(r, wasm)) { + .unresolved => unreachable, + .__wasm_apply_global_tls_relocs, .__wasm_call_ctors, .__wasm_init_memory, .__wasm_init_tls => unreachable, + .object_function => |i| i.ptr(wasm).flags, + .zcu_func => |i| i.flags(wasm), + }; + } + pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { return switch (r.unpack(wasm)) { .unresolved, .zcu_func => true, @@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct { __tls_base, __tls_size, // Next, index into `object_globals`. + // Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. _, @@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct { __tls_base, __tls_size, object_global: ObjectGlobalIndex, + uav_exe: UavsExeIndex, + uav_obj: UavsObjIndex, nav_exe: NavsExeIndex, nav_obj: NavsObjIndex, }; @@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct { return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) }; const comp = wasm.base.comp; const is_obj = comp.config.output_mode == .Obj; - const nav_index = object_global_index - wasm.object_globals.items.len; - return if (is_obj) .{ - .nav_obj = @fromBackingInt(@intCast(nav_index)), - } else .{ - .nav_exe = @fromBackingInt(@intCast(nav_index)), - }; + const uav_index = object_global_index - wasm.object_globals.items.len; + if (is_obj) { + if (uav_index < wasm.uavs_obj.entries.len) { + return .{ .uav_obj = @fromBackingInt(@intCast(uav_index)) }; + } + return .{ .nav_obj = @fromBackingInt( + @intCast(uav_index - wasm.uavs_obj.entries.len), + ) }; + } else { + if (uav_index < wasm.uavs_exe.entries.len) { + return .{ .uav_exe = @fromBackingInt(@intCast(uav_index)) }; + } + return .{ .nav_exe = @fromBackingInt( + @intCast(uav_index - wasm.uavs_exe.entries.len), + ) }; + } }, }; } @@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct { .__tls_base => .__tls_base, .__tls_size => .__tls_size, .object_global => |i| @fromBackingInt(@intCast(first_object_global + @backingInt(i))), - .nav_obj => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))), - .nav_exe => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))), + inline .uav_obj, .uav_exe => |i| @fromBackingInt(@intCast( + first_object_global + wasm.object_globals.items.len + @backingInt(i), + )), + .nav_obj => |i| @fromBackingInt(@intCast( + first_object_global + wasm.object_globals.items.len + + wasm.uavs_obj.entries.len + @backingInt(i), + )), + .nav_exe => |i| @fromBackingInt(@intCast( + first_object_global + wasm.object_globals.items.len + + wasm.uavs_exe.entries.len + @backingInt(i), + )), }; } + pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { + const is_obj = wasm.base.comp.config.output_mode == .Obj; + return pack(wasm, if (is_obj) .{ + .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)), + } else .{ + .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)), + }); + } + pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { const comp = wasm.base.comp; const is_obj = comp.config.output_mode == .Obj; @@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct { return pack(wasm, .{ .object_global = object_global }); } - pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { + pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { + return switch (unpack(r, wasm)) { + .unresolved, + .__heap_base, + .__heap_end, + .__stack_pointer, + .__tls_align, + .__tls_base, + .__tls_size, + => unreachable, + .object_global => |i| i.ptr(wasm).flags, + .uav_obj, .uav_exe, .nav_obj, .nav_exe => unreachable, + }; + } + + pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) ?[]const u8 { return switch (unpack(r, wasm)) { .unresolved => unreachable, .__heap_base => @tagName(Unpacked.__heap_base), @@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct { .__tls_base => @tagName(Unpacked.__tls_base), .__tls_size => @tagName(Unpacked.__tls_size), .object_global => |i| i.name(wasm).slice(wasm), + inline .uav_obj, .uav_exe => |i| std.fmt.bufPrint( + buf, + "__anon_{d}", + .{@backingInt(i.key(wasm).*)}, + ) catch unreachable, .nav_obj => |i| i.name(wasm), .nav_exe => |i| i.name(wasm), }; @@ -1349,6 +1507,22 @@ pub const TableImport = extern struct { return pack(.{ .object_table = object_table }); } + pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { + return switch (unpack(r)) { + .unresolved => unreachable, + .__indirect_function_table => @tagName(Unpacked.__indirect_function_table), + .object_table => |i| i.ptr(wasm).name.slice(wasm), + }; + } + + pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { + return switch (unpack(r)) { + .unresolved => unreachable, + .__indirect_function_table => unreachable, + .object_table => |i| i.ptr(wasm).flags, + }; + } + pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { return switch (unpack(r)) { .unresolved => unreachable, @@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct { unresolved, __zig_error_names, __zig_error_name_table, + __zig_tag_names, + __zig_tag_name_table, __heap_base, __heap_end, /// Next, an `ObjectData.Index`. @@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct { unresolved, __zig_error_names, __zig_error_name_table, + __zig_tag_names, + __zig_tag_name_table, __heap_base, __heap_end, object: ObjectData.Index, @@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct { .unresolved => .unresolved, .__zig_error_names => .__zig_error_names, .__zig_error_name_table => .__zig_error_name_table, + .__zig_tag_names => .__zig_tag_names, + .__zig_tag_name_table => .__zig_tag_name_table, .__heap_base => .__heap_base, .__heap_end => .__heap_end, _ => { @@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct { .unresolved => .unresolved, .__zig_error_names => .__zig_error_names, .__zig_error_name_table => .__zig_error_name_table, + .__zig_tag_names => .__zig_tag_names, + .__zig_tag_name_table => .__zig_tag_name_table, .__heap_base => .__heap_base, .__heap_end => .__heap_end, .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), @@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct { return pack(wasm, .{ .object = object_data_index }); } + pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { + const is_obj = wasm.base.comp.config.output_mode == .Obj; + return pack(wasm, if (is_obj) .{ + .uav_obj = @fromBackingInt(@intCast(wasm.uavs_obj.getIndex(ip_index).?)), + } else .{ + .uav_exe = @fromBackingInt(@intCast(wasm.uavs_exe.getIndex(ip_index).?)), + }); + } + + pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution { + const is_obj = wasm.base.comp.config.output_mode == .Obj; + return pack(wasm, if (is_obj) .{ + .nav_obj = @fromBackingInt(@intCast(wasm.navs_obj.getIndex(nav_index).?)), + } else .{ + .nav_exe = @fromBackingInt(@intCast(wasm.navs_exe.getIndex(nav_index).?)), + }); + } + pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index { return switch (unpack(r, wasm)) { .unresolved => unreachable, .object => |i| i.ptr(wasm).segment, .__zig_error_names, .__zig_error_name_table, + .__zig_tag_names, + .__zig_tag_name_table, .__heap_base, .__heap_end, .uav_exe, @@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct { }, .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 }, .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 }, + .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 }, + .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 }, .__heap_base => .{ .segment = .__heap_base, .offset = 0 }, .__heap_end => .{ .segment = .__heap_end, .offset = 0 }, - .uav_exe => @panic("TODO"), - .uav_obj => @panic("TODO"), - .nav_exe => @panic("TODO"), - .nav_obj => @panic("TODO"), + .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 }, + .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 }, + .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 }, + .nav_obj => |i| .{ .segment = .pack(wasm, .{ .nav_obj = i }), .offset = 0 }, + }; + } + + pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { + return switch (unpack(r, wasm)) { + .unresolved => unreachable, + .__zig_error_names, + .__zig_error_name_table, + .__zig_tag_names, + .__zig_tag_name_table, + => .{ .binding = .local }, + .__heap_base, + .__heap_end, + => unreachable, + .object => |i| i.ptr(wasm).flags, + inline .nav_exe, .nav_obj => |i| { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + const nav = ip.getNav(i.key(wasm).*); + if (nav.getExtern(ip)) |ext| { + const name_slice = ext.name.toSlice(ip); + const name_string = wasm.getExistingString(name_slice).?; + return .{ + .binding = switch (ext.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = switch (ext.visibility) { + .default => false, + .hidden => true, + .protected => false, + }, + .undefined = false, + .exported = wasm.missing_exports.contains(name_string), + .explicit_name = false, + .no_strip = false, + .tls = ext.is_threadlocal, + .absolute = false, + }; + } else { + return .{ + .binding = .local, + .tls = nav.resolved.?.@"threadlocal", + }; + } + }, + .uav_exe, .uav_obj => .{ .binding = .local }, + }; + } + + pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) []const u8 { + return switch (unpack(r, wasm)) { + .unresolved => unreachable, + .object => |i| i.ptr(wasm).name.slice(wasm), + .__zig_error_names => @tagName(.__zig_error_names), + .__zig_error_name_table => @tagName(.__zig_error_name_table), + .__zig_tag_names => @tagName(.__zig_tag_names), + .__zig_tag_name_table => @tagName(.__zig_tag_name_table), + .__heap_base => @tagName(.__heap_base), + .__heap_end => @tagName(.__heap_end), + inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint( + buf, + "__anon_{d}", + .{@backingInt(i.key(wasm).*)}, + ) catch unreachable, + inline .nav_exe, .nav_obj => |i| i.name(wasm), + }; + } + + pub fn size(r: Resolution, wasm: *const Wasm) u32 { + return switch (unpack(r, wasm)) { + .unresolved => unreachable, + .__zig_error_names => @intCast(wasm.error_name_bytes.items.len), + .__zig_error_name_table => { + const comp = wasm.base.comp; + const zcu = comp.zcu.?; + const errors_len = wasm.error_name_offs.items.len; + const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); + return @intCast(errors_len * elem_size); + }, + .__zig_tag_names => @intCast(wasm.tag_name_bytes.items.len), + .__zig_tag_name_table => { + const comp = wasm.base.comp; + const zcu = comp.zcu.?; + const table_len = wasm.tag_name_offs.items.len; + const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); + return @intCast(table_len * elem_size); + }, + .__heap_base, .__heap_end => wasm.pointerSize(), + .object => |i| i.ptr(wasm).size, + inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, }; } }; @@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) { }; } + pub fn isStrings(id: DataSegmentId, wasm: *const Wasm) bool { + return switch (unpack(id, wasm)) { + .__zig_error_names, .__zig_tag_names => true, + + .__zig_error_name_table, + .__zig_tag_name_table, + .__heap_base, + .__heap_end, + => false, + + .object => |i| i.ptr(wasm).flags.strings, + .uav_exe, .uav_obj => false, + .nav_exe, .nav_obj => false, + }; + } + + pub fn isRetain(id: DataSegmentId, wasm: *const Wasm) bool { + return switch (unpack(id, wasm)) { + .__zig_error_names, + .__zig_error_name_table, + .__zig_tag_names, + .__zig_tag_name_table, + .__heap_base, + .__heap_end, + => false, + + .object => |i| i.ptr(wasm).flags.retain, + .uav_exe, .uav_obj => false, + .nav_exe, .nav_obj => false, + }; + } + pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool { return id.category(wasm) == .zero; } @@ -2181,6 +2510,7 @@ const PreloadedStrings = struct { _initialize: String, _start: String, memory: String, + env: String, }; /// Index into string_bytes @@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) { return &wasm.imports.keys()[@backingInt(index)]; } + pub fn flags(index: ZcuImportIndex, wasm: *const Wasm) SymbolFlags { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + const nav_index = index.ptr(wasm).*; + const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern"; + const name_slice = ext.name.toSlice(ip); + const name_string = wasm.getExistingString(name_slice).?; + return .{ + .binding = switch (ext.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = switch (ext.visibility) { + .default => false, + .hidden => true, + .protected => false, + }, + .undefined = true, + .exported = wasm.missing_exports.contains(name_string), + .explicit_name = false, + .no_strip = false, + .tls = ext.is_threadlocal, + .absolute = false, + }; + } + pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String { const zcu = wasm.base.comp.zcu.?; const ip = &zcu.intern_pool; @@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) { } } + pub fn flags(id: FunctionImportId, wasm: *const Wasm) SymbolFlags { + return switch (id.unpack(wasm)) { + .object_function_import => |i| i.value(wasm).flags, + .zcu_import => |i| i.flags(wasm), + }; + } + pub fn importName(id: FunctionImportId, wasm: *const Wasm) String { return switch (unpack(id, wasm)) { inline .object_function_import, .zcu_import => |i| i.importName(wasm), @@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) { } }; -/// 0. Index into `object_global_imports`. -/// 1. Index into `imports`. +/// 0. `__stack_pointer`. +/// 1. Index into `object_global_imports`. +/// 2. Index into `imports`. pub const GlobalImportId = enum(u32) { + __stack_pointer, _, pub const Unpacked = union(enum) { + __stack_pointer, object_global_import: GlobalImport.Index, zcu_import: ZcuImportIndex, }; pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId { return switch (unpacked) { - .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i))), - .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len)), + .__stack_pointer => .__stack_pointer, + .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i) + 1)), + .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len + 1)), }; } pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked { - const i = @backingInt(id); - if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; - const zcu_import_i = i - wasm.object_global_imports.entries.len; - return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; + return switch (id) { + .__stack_pointer => .__stack_pointer, + _ => { + const i = @backingInt(id) - 1; + if (i < wasm.object_global_imports.entries.len) { + return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; + } + const zcu_import_i = i - wasm.object_global_imports.entries.len; + return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; + }, + }; } pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId { return pack(.{ .object_global_import = object_global_import }, wasm); } + pub fn flags(id: GlobalImportId, wasm: *const Wasm) SymbolFlags { + return switch (id.unpack(wasm)) { + .__stack_pointer => .{ + .binding = .strong, + .undefined = true, + }, + .object_global_import => |i| i.value(wasm).flags, + .zcu_import => |i| i.flags(wasm), + }; + } + /// This function is allowed O(N) lookup because it is only called during /// diagnostic generation. pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { switch (id.unpack(wasm)) { + .__stack_pointer => return .zig_object_nofile, .object_global_import => |obj_global_index| { // TODO binary search for (wasm.objects.items, 0..) |o, i| { @@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) { pub fn importName(id: GlobalImportId, wasm: *const Wasm) String { return switch (unpack(id, wasm)) { + .__stack_pointer => wasm.preloaded_strings.__stack_pointer, inline .object_global_import, .zcu_import => |i| i.importName(wasm), }; } pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString { return switch (unpack(id, wasm)) { + .__stack_pointer => wasm.preloaded_strings.env.toOptional(), inline .object_global_import, .zcu_import => |i| i.moduleName(wasm), }; } pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type { return switch (unpack(id, wasm)) { + .__stack_pointer => .{ + .valtype = switch (wasm.pointerSize()) { + 4 => .i32, + 8 => .i64, + else => unreachable, + }, + .mutable = true, + }, inline .object_global_import, .zcu_import => |i| i.globalType(wasm), }; } @@ -2482,6 +2880,13 @@ pub const DataImportId = enum(u32) { return pack(.{ .object_data_import = object_data_import }, wasm); } + pub fn flags(id: DataImportId, wasm: *const Wasm) SymbolFlags { + return switch (id.unpack(wasm)) { + .object_data_import => |i| i.value(wasm).flags, + .zcu_import => |i| i.flags(wasm), + }; + } + pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation { switch (id.unpack(wasm)) { .object_data_import => |obj_data_index| { @@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) { } }; -/// Index into `Wasm.symbol_table`. -pub const SymbolTableIndex = enum(u32) { - _, - - pub fn key(i: @This(), wasm: *const Wasm) *String { - return &wasm.symbol_table.keys()[@backingInt(i)]; - } -}; - -pub const OutReloc = struct { +pub const ZcuRelocation = struct { tag: Object.RelocationType, offset: u32, pointee: Pointee, addend: i32, - pub const Pointee = union { - symbol_index: SymbolTableIndex, + pub const Pointee = union(enum) { + function_nav: InternPool.Nav.Index, + function_name: String, + tag_function: InternPool.Index, + data_uav: InternPool.Index, + data_nav: InternPool.Nav.Index, + data_resolution: ObjectDataImport.Resolution, + stack_pointer, type_index: FunctionType.Index, }; pub const Slice = extern struct { - /// Index into `out_relocs`. + /// Index into `zcu_relocations`. off: u32, len: u32, - pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc { - return wasm.relocations.items[s.off..][0..s.len]; + pub fn tags(s: Slice, wasm: *const Wasm) []const Object.RelocationType { + return wasm.zcu_relocations.items(.tag)[s.off..][0..s.len]; + } + + pub fn offsets(s: Slice, wasm: *const Wasm) []const u32 { + return wasm.zcu_relocations.items(.offset)[s.off..][0..s.len]; + } + + pub fn pointees(s: Slice, wasm: *const Wasm) []const Pointee { + return wasm.zcu_relocations.items(.pointee)[s.off..][0..s.len]; + } + + pub fn addends(s: Slice, wasm: *const Wasm) []const i32 { + return wasm.zcu_relocations.items(.addend)[s.off..][0..s.len]; } }; }; @@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void { wasm.table_imports.deinit(gpa); wasm.tables.deinit(gpa); wasm.data_imports.deinit(gpa); + wasm.datas.deinit(gpa); wasm.data_segments.deinit(gpa); - wasm.symbol_table.deinit(gpa); - wasm.out_relocs.deinit(gpa); + wasm.zcu_relocations.deinit(gpa); wasm.uav_fixups.deinit(gpa); wasm.nav_fixups.deinit(gpa); wasm.func_table_fixups.deinit(gpa); @@ -3351,6 +3765,25 @@ pub fn updateExports( const zcu = pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; + const is_obj = wasm.base.comp.config.output_mode == .Obj; + switch (exported) { + .nav => {}, // handled in updateNav + .uav => |uav_index| { // export may be the only reference + const zds: ZcuDataStarts = .init(wasm); + if (is_obj) { + const gop = try wasm.uavs_obj.getOrPut(gpa, uav_index); + if (!gop.found_existing) gop.value_ptr.* = undefined; + } else { + const gop = try wasm.uavs_exe.getOrPut(gpa, uav_index); + if (!gop.found_existing) gop.value_ptr.* = .{ + .code = undefined, + .count = 0, + }; + gop.value_ptr.count += 1; + } + try zds.finish(wasm, pt); + }, + } for (export_indices) |export_idx| { const exp = export_idx.ptr(zcu); const name_slice = exp.opts.name.toSlice(ip); @@ -3443,7 +3876,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { // Zig always depends on a stack pointer global. // If emitting an object, it's an import. Otherwise, the linker synthesizes it. if (is_obj) { - @panic("TODO"); + try wasm.global_imports.putNoClobber( + gpa, + wasm.preloaded_strings.__stack_pointer, + .__stack_pointer, + ); } else { try wasm.globals.put(gpa, .__stack_pointer, {}); assert(wasm.globals.entries.len - 1 == @backingInt(GlobalIndex.stack_pointer)); @@ -3453,7 +3890,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { // These loops do both recursive marking of alive symbols well as checking for undefined symbols. // At the end, output functions and globals will be populated. for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { - if (import.flags.isIncluded(rdynamic)) { + if (import.flags.isIncluded(rdynamic, is_obj)) { try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } @@ -3467,7 +3904,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { - if (import.flags.isIncluded(rdynamic)) { + if (import.flags.isIncluded(rdynamic, is_obj)) { try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } @@ -3475,13 +3912,13 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { wasm.global_exports_len = @intCast(wasm.global_exports.items.len); for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { - if (import.flags.isIncluded(rdynamic)) { + if (import.flags.isIncluded(rdynamic, is_obj)) { try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } for (wasm.object_data_imports.keys(), wasm.object_data_imports.values(), 0..) |name, *import, i| { - if (import.flags.isIncluded(rdynamic)) { + if (import.flags.isIncluded(rdynamic, is_obj)) { try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } @@ -3512,18 +3949,23 @@ pub fn markFunctionImport( const comp = wasm.base.comp; const gpa = comp.gpa; + const is_obj = comp.config.output_mode == .Obj; try wasm.functions.ensureUnusedCapacity(gpa, 1); if (import.resolution == .unresolved) { - if (name == wasm.preloaded_strings.__wasm_init_memory) { - try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); - } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { - try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); - } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { - try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); - } else if (name == wasm.preloaded_strings.__wasm_init_tls) { - try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); + if (!is_obj) { + if (name == wasm.preloaded_strings.__wasm_init_memory) { + try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); + } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { + try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); + } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { + try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); + } else if (name == wasm.preloaded_strings.__wasm_init_tls) { + try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); + } else { + try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); + } } else { try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); } @@ -3576,28 +4018,33 @@ fn markGlobalImport( const comp = wasm.base.comp; const gpa = comp.gpa; + const is_obj = comp.config.output_mode == .Obj; try wasm.globals.ensureUnusedCapacity(gpa, 1); if (import.resolution == .unresolved) { - if (name == wasm.preloaded_strings.__heap_base) { - import.resolution = .__heap_base; - wasm.globals.putAssumeCapacity(.__heap_base, {}); - } else if (name == wasm.preloaded_strings.__heap_end) { - import.resolution = .__heap_end; - wasm.globals.putAssumeCapacity(.__heap_end, {}); - } else if (name == wasm.preloaded_strings.__stack_pointer) { - import.resolution = .__stack_pointer; - wasm.globals.putAssumeCapacity(.__stack_pointer, {}); - } else if (name == wasm.preloaded_strings.__tls_align) { - import.resolution = .__tls_align; - wasm.globals.putAssumeCapacity(.__tls_align, {}); - } else if (name == wasm.preloaded_strings.__tls_base) { - import.resolution = .__tls_base; - wasm.globals.putAssumeCapacity(.__tls_base, {}); - } else if (name == wasm.preloaded_strings.__tls_size) { - import.resolution = .__tls_size; - wasm.globals.putAssumeCapacity(.__tls_size, {}); + if (!is_obj) { + if (name == wasm.preloaded_strings.__heap_base) { + import.resolution = .__heap_base; + wasm.globals.putAssumeCapacity(.__heap_base, {}); + } else if (name == wasm.preloaded_strings.__heap_end) { + import.resolution = .__heap_end; + wasm.globals.putAssumeCapacity(.__heap_end, {}); + } else if (name == wasm.preloaded_strings.__stack_pointer) { + import.resolution = .__stack_pointer; + wasm.globals.putAssumeCapacity(.__stack_pointer, {}); + } else if (name == wasm.preloaded_strings.__tls_align) { + import.resolution = .__tls_align; + wasm.globals.putAssumeCapacity(.__tls_align, {}); + } else if (name == wasm.preloaded_strings.__tls_base) { + import.resolution = .__tls_base; + wasm.globals.putAssumeCapacity(.__tls_base, {}); + } else if (name == wasm.preloaded_strings.__tls_size) { + import.resolution = .__tls_size; + wasm.globals.putAssumeCapacity(.__tls_size, {}); + } else { + try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); + } } else { try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); } @@ -3625,7 +4072,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err try wasm.markRelocations(global.relocations(wasm)); } -fn markTableImport( +pub fn markTableImport( wasm: *Wasm, name: String, import: *TableImport, @@ -3636,13 +4083,18 @@ fn markTableImport( const comp = wasm.base.comp; const gpa = comp.gpa; + const is_obj = comp.config.output_mode == .Obj; try wasm.tables.ensureUnusedCapacity(gpa, 1); if (import.resolution == .unresolved) { - if (name == wasm.preloaded_strings.__indirect_function_table) { - import.resolution = .__indirect_function_table; - wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); + if (!is_obj) { + if (name == wasm.preloaded_strings.__indirect_function_table) { + import.resolution = .__indirect_function_table; + wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); + } else { + try wasm.table_imports.put(gpa, name, table_index); + } } else { try wasm.table_imports.put(gpa, name, table_index); } @@ -3676,22 +4128,38 @@ pub fn markDataImport( const comp = wasm.base.comp; const gpa = comp.gpa; + const is_obj = comp.config.output_mode == .Obj; + + try wasm.data_segments.ensureUnusedCapacity(gpa, 1); if (import.resolution == .unresolved) { - if (name == wasm.preloaded_strings.__heap_base) { - import.resolution = .__heap_base; - wasm.data_segments.putAssumeCapacity(.__heap_base, {}); - } else if (name == wasm.preloaded_strings.__heap_end) { - import.resolution = .__heap_end; - wasm.data_segments.putAssumeCapacity(.__heap_end, {}); + if (!is_obj) { + if (name == wasm.preloaded_strings.__heap_base) { + import.resolution = .__heap_base; + wasm.data_segments.putAssumeCapacity(.__heap_base, {}); + } else if (name == wasm.preloaded_strings.__heap_end) { + import.resolution = .__heap_end; + wasm.data_segments.putAssumeCapacity(.__heap_end, {}); + } else { + try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); + } } else { try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); } - } else if (import.resolution.objectDataSegment(wasm)) |segment_index| { - try markDataSegment(wasm, segment_index); + } else switch (import.resolution.unpack(wasm)) { + .object => |object_data_index| try markData(wasm, object_data_index), + else => {}, } } +fn markData(wasm: *Wasm, i: ObjectData.Index) link.Error!void { + const gpa = wasm.base.comp.gpa; + const gop = try wasm.datas.getOrPut(gpa, .fromObjectDataIndex(wasm, i)); + if (gop.found_existing) return; + + try markDataSegment(wasm, i.ptr(wasm).segment); +} + fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void { const gpa = wasm.base.comp.gpa; for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, pointee, offset| { @@ -3782,7 +4250,7 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Err .memory_addr_tls_sleb, .memory_addr_locrel_i32, .memory_addr_tls_sleb64, - => try markDataSegment(wasm, pointee.data.ptr(wasm).segment), + => try markData(wasm, pointee.data), .type_index_leb => continue, } @@ -3829,7 +4297,13 @@ pub fn flush( const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len); defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu); + const global_exports_end_zcu: u32 = @intCast(wasm.global_exports.items.len); + defer wasm.global_exports.shrinkRetainingCapacity(global_exports_end_zcu); + wasm.flush_buffer.clear(); + wasm.tag_name_bytes.clearRetainingCapacity(); + wasm.tag_name_offs.clearRetainingCapacity(); + wasm.tag_name_table_ref_count = 0; try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); try wasm.flush_buffer.global_imports.reinit(gpa, wasm.global_imports.keys(), wasm.global_imports.values()); @@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType( }); } +fn internIntrinsicType( + wasm: *Wasm, + params: []const InternPool.Index, + return_type: Zcu.Type, +) Allocator.Error!FunctionType.Index { + const target = &wasm.base.comp.root_mod.resolved_target.result; + return wasm.internFunctionType(.{ .wasm_mvp = .{} }, params, return_type, false, target); +} + +pub fn intrinsicFunctionType(wasm: *Wasm, intrinsic: Mir.Intrinsic) Allocator.Error!FunctionType.Index { + return switch (intrinsic) { + .__addhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__addtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .__addxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__ashlti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), + .__ashrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), + .__bitreversedi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64), + .__bitreversesi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32), + .__bswapdi2 => internIntrinsicType(wasm, &.{.u64_type}, .u64), + .__bswapsi2 => internIntrinsicType(wasm, &.{.u32_type}, .u32), + .__ceilh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__ceilx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__cosh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__cosx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__divei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), + .__divhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__divtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .__divti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), + .__divxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__eqtf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__eqxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__exp2h => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__exp2x => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__exph => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__expx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__extenddftf2 => internIntrinsicType(wasm, &.{.f64_type}, .f128), + .__extenddfxf2 => internIntrinsicType(wasm, &.{.f64_type}, .f80), + .__extendhfsf2 => internIntrinsicType(wasm, &.{.f16_type}, .f32), + .__extendhftf2 => internIntrinsicType(wasm, &.{.f16_type}, .f128), + .__extendhfxf2 => internIntrinsicType(wasm, &.{.f16_type}, .f80), + .__extendsftf2 => internIntrinsicType(wasm, &.{.f32_type}, .f128), + .__extendsfxf2 => internIntrinsicType(wasm, &.{.f32_type}, .f80), + .__extendxftf2 => internIntrinsicType(wasm, &.{.f80_type}, .f128), + .__fabsh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__fabsx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__fixdfdi => internIntrinsicType(wasm, &.{.f64_type}, .i64), + .__fixdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void), + .__fixdfsi => internIntrinsicType(wasm, &.{.f64_type}, .i32), + .__fixdfti => internIntrinsicType(wasm, &.{.f64_type}, .i128), + .__fixhfdi => internIntrinsicType(wasm, &.{.f16_type}, .i64), + .__fixhfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void), + .__fixhfsi => internIntrinsicType(wasm, &.{.f16_type}, .i32), + .__fixhfti => internIntrinsicType(wasm, &.{.f16_type}, .i128), + .__fixsfdi => internIntrinsicType(wasm, &.{.f32_type}, .i64), + .__fixsfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void), + .__fixsfsi => internIntrinsicType(wasm, &.{.f32_type}, .i32), + .__fixsfti => internIntrinsicType(wasm, &.{.f32_type}, .i128), + .__fixtfdi => internIntrinsicType(wasm, &.{.f128_type}, .i64), + .__fixtfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void), + .__fixtfsi => internIntrinsicType(wasm, &.{.f128_type}, .i32), + .__fixtfti => internIntrinsicType(wasm, &.{.f128_type}, .i128), + .__fixunsdfdi => internIntrinsicType(wasm, &.{.f64_type}, .u64), + .__fixunsdfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f64_type }, .void), + .__fixunsdfsi => internIntrinsicType(wasm, &.{.f64_type}, .u32), + .__fixunsdfti => internIntrinsicType(wasm, &.{.f64_type}, .u128), + .__fixunshfdi => internIntrinsicType(wasm, &.{.f16_type}, .u64), + .__fixunshfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f16_type }, .void), + .__fixunshfsi => internIntrinsicType(wasm, &.{.f16_type}, .u32), + .__fixunshfti => internIntrinsicType(wasm, &.{.f16_type}, .u128), + .__fixunssfdi => internIntrinsicType(wasm, &.{.f32_type}, .u64), + .__fixunssfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f32_type }, .void), + .__fixunssfsi => internIntrinsicType(wasm, &.{.f32_type}, .u32), + .__fixunssfti => internIntrinsicType(wasm, &.{.f32_type}, .u128), + .__fixunstfdi => internIntrinsicType(wasm, &.{.f128_type}, .u64), + .__fixunstfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f128_type }, .void), + .__fixunstfsi => internIntrinsicType(wasm, &.{.f128_type}, .u32), + .__fixunstfti => internIntrinsicType(wasm, &.{.f128_type}, .u128), + .__fixunsxfdi => internIntrinsicType(wasm, &.{.f80_type}, .u64), + .__fixunsxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void), + .__fixunsxfsi => internIntrinsicType(wasm, &.{.f80_type}, .u32), + .__fixunsxfti => internIntrinsicType(wasm, &.{.f80_type}, .u128), + .__fixxfdi => internIntrinsicType(wasm, &.{.f80_type}, .i64), + .__fixxfei => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .f80_type }, .void), + .__fixxfsi => internIntrinsicType(wasm, &.{.f80_type}, .i32), + .__fixxfti => internIntrinsicType(wasm, &.{.f80_type}, .i128), + .__floatdidf => internIntrinsicType(wasm, &.{.i64_type}, .f64), + .__floatdihf => internIntrinsicType(wasm, &.{.i64_type}, .f16), + .__floatdisf => internIntrinsicType(wasm, &.{.i64_type}, .f32), + .__floatditf => internIntrinsicType(wasm, &.{.i64_type}, .f128), + .__floatdixf => internIntrinsicType(wasm, &.{.i64_type}, .f80), + .__floateidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64), + .__floateihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16), + .__floateisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32), + .__floateitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128), + .__floateixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80), + .__floatsidf => internIntrinsicType(wasm, &.{.i32_type}, .f64), + .__floatsihf => internIntrinsicType(wasm, &.{.i32_type}, .f16), + .__floatsisf => internIntrinsicType(wasm, &.{.i32_type}, .f32), + .__floatsitf => internIntrinsicType(wasm, &.{.i32_type}, .f128), + .__floatsixf => internIntrinsicType(wasm, &.{.i32_type}, .f80), + .__floattidf => internIntrinsicType(wasm, &.{.i128_type}, .f64), + .__floattihf => internIntrinsicType(wasm, &.{.i128_type}, .f16), + .__floattisf => internIntrinsicType(wasm, &.{.i128_type}, .f32), + .__floattitf => internIntrinsicType(wasm, &.{.i128_type}, .f128), + .__floattixf => internIntrinsicType(wasm, &.{.i128_type}, .f80), + .__floatundidf => internIntrinsicType(wasm, &.{.u64_type}, .f64), + .__floatundihf => internIntrinsicType(wasm, &.{.u64_type}, .f16), + .__floatundisf => internIntrinsicType(wasm, &.{.u64_type}, .f32), + .__floatunditf => internIntrinsicType(wasm, &.{.u64_type}, .f128), + .__floatundixf => internIntrinsicType(wasm, &.{.u64_type}, .f80), + .__floatuneidf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f64), + .__floatuneihf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f16), + .__floatuneisf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f32), + .__floatuneitf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f128), + .__floatuneixf => internIntrinsicType(wasm, &.{ .usize_type, .usize_type }, .f80), + .__floatunsidf => internIntrinsicType(wasm, &.{.u32_type}, .f64), + .__floatunsihf => internIntrinsicType(wasm, &.{.u32_type}, .f16), + .__floatunsisf => internIntrinsicType(wasm, &.{.u32_type}, .f32), + .__floatunsitf => internIntrinsicType(wasm, &.{.u32_type}, .f128), + .__floatunsixf => internIntrinsicType(wasm, &.{.u32_type}, .f80), + .__floatuntidf => internIntrinsicType(wasm, &.{.u128_type}, .f64), + .__floatuntihf => internIntrinsicType(wasm, &.{.u128_type}, .f16), + .__floatuntisf => internIntrinsicType(wasm, &.{.u128_type}, .f32), + .__floatuntitf => internIntrinsicType(wasm, &.{.u128_type}, .f128), + .__floatuntixf => internIntrinsicType(wasm, &.{.u128_type}, .f80), + .__floorh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__floorx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__fmah => internIntrinsicType(wasm, &.{ .f16_type, .f16_type, .f16_type }, .f16), + .__fmax => internIntrinsicType(wasm, &.{ .f80_type, .f80_type, .f80_type }, .f80), + .__fmaxh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__fmaxx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__fminh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__fminx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__fmodh => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__fmodx => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__getf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__gexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__gttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__gtxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__letf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__lexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__log10h => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__log10x => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__log2h => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__log2x => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__logh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__logx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__lshrti3 => internIntrinsicType(wasm, &.{ .i128_type, .i32_type }, .i128), + .__lttf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__ltxf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__modei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), + .__modti3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), + .__mulhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__mulodi4 => internIntrinsicType(wasm, &.{ .i64_type, .i64_type, .usize_type }, .i64), + .__muloti4 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type, .usize_type }, .i128), + .__multf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .__multi3 => internIntrinsicType(wasm, &.{ .i128_type, .i128_type }, .i128), + .__mulxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__netf2 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .bool), + .__nexf2 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .bool), + .__roundh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__roundx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__sinh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__sinx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__sqrth => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__sqrtx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__subhf3 => internIntrinsicType(wasm, &.{ .f16_type, .f16_type }, .f16), + .__subtf3 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .__subxf3 => internIntrinsicType(wasm, &.{ .f80_type, .f80_type }, .f80), + .__tanh => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__tanx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__trunch => internIntrinsicType(wasm, &.{.f16_type}, .f16), + .__truncsfhf2 => internIntrinsicType(wasm, &.{.f32_type}, .f16), + .__trunctfdf2 => internIntrinsicType(wasm, &.{.f128_type}, .f64), + .__trunctfhf2 => internIntrinsicType(wasm, &.{.f128_type}, .f16), + .__trunctfsf2 => internIntrinsicType(wasm, &.{.f128_type}, .f32), + .__trunctfxf2 => internIntrinsicType(wasm, &.{.f128_type}, .f80), + .__truncx => internIntrinsicType(wasm, &.{.f80_type}, .f80), + .__truncxfdf2 => internIntrinsicType(wasm, &.{.f80_type}, .f64), + .__truncxfhf2 => internIntrinsicType(wasm, &.{.f80_type}, .f16), + .__truncxfsf2 => internIntrinsicType(wasm, &.{.f80_type}, .f32), + .__udivei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), + .__udivti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), + .__umodei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), + .__umodti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), + .ceilq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .cos => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .cosf => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .cosq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .exp => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .exp2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .exp2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .exp2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .expf => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .expq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .fabsq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .floorq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .fma => internIntrinsicType(wasm, &.{ .f64_type, .f64_type, .f64_type }, .f64), + .fmaf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type, .f32_type }, .f32), + .fmaq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type, .f128_type }, .f128), + .fmax => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), + .fmaxf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), + .fmaxq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .fmin => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), + .fminf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), + .fminq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .fmod => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), + .fmodf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), + .fmodq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .log => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .log10 => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .log10f => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .log10q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .log2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .log2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .log2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .logf => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .logq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .roundq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .sin => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .sinf => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .sinq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .sqrtq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .tan => internIntrinsicType(wasm, &.{.f64_type}, .f64), + .tanf => internIntrinsicType(wasm, &.{.f32_type}, .f32), + .tanq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .truncq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .memcpy => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), + .memmove => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), + .memset => internIntrinsicType(wasm, &.{ .usize_type, .i32_type, .usize_type }, .usize), + .__addo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), + .__subo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), + .__cmp_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .i8), + .__and_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), + .__or_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), + .__xor_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .u16_type }, .void), + .__not_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), + .__shlo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .bool), + .__shr_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type, .bool_type, .u16_type }, .void), + .__clz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), + .__ctz_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), + .__popcount_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .u16_type }, .u16), + .__bitreverse_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), + .__byteswap_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .bool_type, .u16_type }, .void), + .__mulo_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .bool_type, .u16_type }, .bool), + .__abs_limb64 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .u16_type }, .void), + }; +} + pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { const gpa = wasm.base.comp.gpa; // We can't use string table deduplication here since these expressions can @@ -3972,64 +4695,63 @@ pub fn addRelocatableDataPayload(wasm: *Wasm, bytes: []const u8) Allocator.Error }; } -pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { +pub fn addNavReloc( + wasm: *Wasm, + reloc_offset: usize, + nav_index: InternPool.Nav.Index, + nav_ty: Zcu.Type, + addend: u32, +) !void { const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); - const gpa = comp.gpa; - const name = try wasm.internStringFmt("__anon_{d}", .{@backingInt(ip_index)}); - const gop = try wasm.symbol_table.getOrPut(gpa, name); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); -} - -pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex { - const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); const zcu = comp.zcu.?; const ip = &zcu.intern_pool; const gpa = comp.gpa; - const nav = ip.getNav(nav_index); - const name = try wasm.internString(nav.fqn.toSlice(ip)); - const gop = try wasm.symbol_table.getOrPut(gpa, name); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); -} -pub fn errorNameTableSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex { - const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); - const gpa = comp.gpa; - const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__zig_error_name_table); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); -} + const is_obj = comp.config.output_mode == .Obj; -pub fn stackPointerSymbolIndex(wasm: *Wasm) Allocator.Error!SymbolTableIndex { - const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); - const gpa = comp.gpa; - const gop = try wasm.symbol_table.getOrPut(gpa, wasm.preloaded_strings.__stack_pointer); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); -} - -pub fn tagTableIndexSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { - const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); - const gpa = comp.gpa; - const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{ip_index}); - const gop = try wasm.symbol_table.getOrPut(gpa, name); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); -} - -pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableIndex { - const comp = wasm.base.comp; - assert(comp.config.output_mode == .Obj); - const gpa = comp.gpa; - const gop = try wasm.symbol_table.getOrPut(gpa, name); - gop.value_ptr.* = {}; - return @fromBackingInt(@intCast(gop.index)); + if (nav_ty.zigTypeTag(zcu) == .@"fn") { + const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); + if (!gop.found_existing) gop.value_ptr.* = {}; + if (is_obj) { + assert(addend == 0); + try wasm.zcu_relocations.append(gpa, .{ + .offset = @intCast(reloc_offset), + .pointee = .{ .function_nav = nav_index }, + .tag = switch (wasm.pointerSize()) { + 4 => .table_index_i32, + 8 => .table_index_i64, + else => unreachable, + }, + .addend = 0, + }); + } else { + try wasm.func_table_fixups.append(gpa, .{ + .nav_index = nav_index, + .offset = @intCast(reloc_offset), + }); + } + } else { + if (is_obj) { + if (ip.getNav(nav_index).getExtern(ip) == null) _ = try wasm.refNavObj(nav_index); + try wasm.zcu_relocations.append(gpa, .{ + .offset = @intCast(reloc_offset), + .pointee = .{ .data_nav = nav_index }, + .tag = switch (wasm.pointerSize()) { + 4 => .memory_addr_i32, + 8 => .memory_addr_i64, + else => unreachable, + }, + .addend = @intCast(addend), + }); + } else { + try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); + wasm.nav_fixups.appendAssumeCapacity(.{ + .nav_index = nav_index, + .offset = @intCast(reloc_offset), + .addend = addend, + }); + } + } } pub fn addUavReloc( @@ -4057,12 +4779,12 @@ pub fn addUavReloc( 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, .{ + try wasm.zcu_relocations.append(gpa, .{ .offset = @intCast(reloc_offset), - .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) }, + .pointee = .{ .data_uav = uav_val }, .tag = switch (wasm.pointerSize()) { - 32 => .memory_addr_i32, - 64 => .memory_addr_i64, + 4 => .memory_addr_i32, + 8 => .memory_addr_i64, else => unreachable, }, .addend = @intCast(addend), @@ -4085,7 +4807,7 @@ pub fn addUavReloc( pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex { const comp = wasm.base.comp; const gpa = comp.gpa; - assert(comp.config.output_mode != .Obj); + assert(comp.config.output_mode == .Obj); const gop = try wasm.navs_obj.getOrPut(gpa, nav_index); if (!gop.found_existing) gop.value_ptr.* = .{ // Lowering the value is delayed to avoid recursion. @@ -4113,7 +4835,7 @@ 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, ip_index: InternPool.Index) u32 { +pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 { assert(wasm.flush_buffer.memory_layout_finished); const comp = wasm.base.comp; assert(comp.config.output_mode != .Obj); @@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { } /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. -pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { +pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 { assert(wasm.flush_buffer.memory_layout_finished); const comp = wasm.base.comp; assert(comp.config.output_mode != .Obj); @@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { if (wasm.object_data_imports.getPtr(symbol_name)) |import| { switch (import.resolution.unpack(wasm)) { - .unresolved => unreachable, + .unresolved => {}, .object => |object_data_index| { const object_data = object_data_index.ptr(wasm); const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment); const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?; return segment_base_addr + object_data.offset; }, - .__zig_error_names => @panic("TODO"), - .__zig_error_name_table => @panic("TODO"), - .__heap_base => @panic("TODO"), - .__heap_end => @panic("TODO"), - .uav_exe => @panic("TODO"), - .uav_obj => @panic("TODO"), - .nav_exe => @panic("TODO"), - .nav_obj => @panic("TODO"), + .__heap_base, + .__heap_end, + .uav_exe, + .nav_exe, + => { + const data_loc = import.resolution.dataLoc(wasm); + return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset; + }, + .__zig_error_names, + .__zig_error_name_table, + .__zig_tag_names, + .__zig_tag_name_table, + .uav_obj, + .nav_obj, + => unreachable, } } + if (wasm.flush_buffer.data_exports.get(symbol_name)) |symbol| { + const data_loc = symbol.resolution.dataLoc(wasm); + return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset; + } }, else => {}, } @@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { assert(comp.config.output_mode != .Obj); const f = &wasm.flush_buffer; const table_base_addr = f.data_segments.get(.__zig_tag_name_table).?; - const table_index = f.enum_tag_name_table.get(ip_index).?; - return table_base_addr + table_index * 8; + return table_base_addr + wasm.tagIndexTableOffset(ip_index); +} + +pub fn tagIndexTableOffset(wasm: *const Wasm, ip_index: InternPool.Index) u32 { + const table_index = wasm.flush_buffer.enum_tag_name_table.get(ip_index).?; + return table_index * wasm.pointerSize() * 2; } fn convertZcuFnType( @@ -4255,7 +4992,7 @@ pub fn isBss(wasm: *const Wasm, optional_name: OptionalString) bool { /// those entries. fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj { const code_start: u32 = @intCast(wasm.string_bytes.items.len); - const relocs_start: u32 = @intCast(wasm.out_relocs.len); + const relocs_start: u32 = @intCast(wasm.zcu_relocations.len); const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len); const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len); const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len); @@ -4271,8 +5008,9 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu } const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); - const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); + const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start); const any_fixups = + relocs_len != 0 or uav_fixups_start != wasm.uav_fixups.items.len or nav_fixups_start != wasm.nav_fixups.items.len or func_table_fixups_start != wasm.func_table_fixups.items.len; diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index ac580f9bbc5656362185489f457f15b387605a68..45633149611c318bb5623d6cbb5ba75bcab77f5a 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -7,7 +7,6 @@ const Object = @import("Object.zig"); const Zcu = @import("../../Zcu.zig"); const Alignment = Wasm.Alignment; const String = Wasm.String; -const Relocation = Wasm.Relocation; const InternPool = @import("../../InternPool.zig"); const Mir = @import("../../codegen/wasm/Mir.zig"); @@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty, binary_bytes: ArrayList(u8) = .empty, missing_exports: std.array_hash_map.Auto(String, void) = .empty, function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty, +intrinsic_function_imports: std.array_hash_map.Auto(String, Wasm.FunctionType.Index) = .empty, +/// Function aliases emitted after function symbols. +function_export_symbols: std.array_hash_map.Auto(String, FunctionExportSymbol) = .empty, global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty, data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty, +/// Data aliases emitted after data symbols. +data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty, indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty, @@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty, enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty, +code_relocs: std.ArrayList(Relocation) = .empty, +data_relocs: std.ArrayList(Relocation) = .empty, + /// For debug purposes only. memory_layout_finished: bool = false, @@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) { } }; +/// Index into SYMTAB_FUNCTION. +const FunctionSymbolIndex = enum(u32) { + _, + + fn fromOutputFunctionIndex(i: Wasm.OutputFunctionIndex) FunctionSymbolIndex { + return @fromBackingInt(@backingInt(i)); + } + + fn fromObjectFunctionHandlingWeak(wasm: *const Wasm, index: Wasm.ObjectFunctionIndex) FunctionSymbolIndex { + return fromOutputFunctionIndex(.fromObjectFunctionHandlingWeak(wasm, index)); + } + + fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) FunctionSymbolIndex { + return fromOutputFunctionIndex(.fromIpNav(wasm, nav_index)); + } + + fn fromTagIndexType(wasm: *const Wasm, ip_index: InternPool.Index) FunctionSymbolIndex { + return fromOutputFunctionIndex(.fromTagIndexType(wasm, ip_index)); + } + + fn fromSymbolName(wasm: *const Wasm, name: String) FunctionSymbolIndex { + const f = &wasm.flush_buffer; + if (f.function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); + if (f.intrinsic_function_imports.getIndex(name)) |i| return @fromBackingInt(@intCast( + f.function_imports.entries.len + i, + )); + if (f.function_export_symbols.getIndex(name)) |i| return @fromBackingInt(@intCast( + f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + + wasm.functions.entries.len + i, + )); + return fromOutputFunctionIndex(.fromSymbolName(wasm, name)); + } +}; + +/// Index into SYMTAB_DATA. +const DataSymbolIndex = enum(u32) { + _, + + fn fromOutputDataIndex(i: Wasm.OutputDataIndex) DataSymbolIndex { + return @fromBackingInt(@backingInt(i)); + } + + fn fromResolution(wasm: *const Wasm, resolution: Wasm.ObjectDataImport.Resolution) DataSymbolIndex { + return fromOutputDataIndex(Wasm.OutputDataIndex.fromResolution(wasm, resolution).?); + } + + fn fromObjectData(wasm: *const Wasm, index: Wasm.ObjectData.Index) DataSymbolIndex { + return fromOutputDataIndex(.fromObjectData(wasm, index)); + } + + fn fromUav(wasm: *const Wasm, ip_index: InternPool.Index) DataSymbolIndex { + return fromOutputDataIndex(.fromUav(wasm, ip_index)); + } + + fn fromNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) DataSymbolIndex { + return fromOutputDataIndex(.fromNav(wasm, nav_index)); + } + + fn fromSymbolName(wasm: *const Wasm, name: String) DataSymbolIndex { + const f = &wasm.flush_buffer; + if (f.data_imports.getIndex(name)) |i| return @fromBackingInt(@intCast(i)); + if (f.data_exports.getIndex(name)) |i| return @fromBackingInt(@intCast( + f.data_imports.entries.len + wasm.datas.entries.len + i, + )); + return fromOutputDataIndex(.fromSymbolName(wasm, name)); + } +}; + /// Index into `indirect_function_table`. const IndirectFunctionTableIndex = enum(u32) { _, @@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) { return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?)); } - fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex { - // These are the same since those are added to the table first. - return @fromBackingInt(@intCast(@backingInt(i))); + fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) IndirectFunctionTableIndex { + return fromOutputFunctionIndex(&wasm.flush_buffer, .fromIpNav(wasm, nav_index)); } fn toAbi(i: IndirectFunctionTableIndex) u32 { @@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) { } }; +const SymbolTableOffsets = struct { + function: u32, + data: u32, + global: u32, + table: u32, +}; + +const FunctionExportSymbol = struct { + function_index: Wasm.FunctionIndex, + flags: Wasm.SymbolFlags, +}; + +const DataExportSymbol = struct { + resolution: Wasm.ObjectDataImport.Resolution, + flags: Wasm.SymbolFlags, +}; + +const Relocation = struct { + tag: Object.RelocationType, + offset: u32, + pointee: Pointee, + addend: i32, + + const Pointee = union { + data: DataSymbolIndex, + type_index: FuncTypeIndex, + section: Wasm.ObjectSectionIndex, + function: FunctionSymbolIndex, + global: Wasm.GlobalIndex, + table: Wasm.TableIndex, + }; +}; + const DataSegmentGroup = struct { first_segment: Wasm.DataSegmentId, end_addr: u32, @@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void { f.data_segments.clearRetainingCapacity(); f.data_segment_groups.clearRetainingCapacity(); f.binary_bytes.clearRetainingCapacity(); + f.intrinsic_function_imports.clearRetainingCapacity(); + f.function_export_symbols.clearRetainingCapacity(); + f.data_exports.clearRetainingCapacity(); f.indirect_function_table.clearRetainingCapacity(); f.func_types.clearRetainingCapacity(); f.enum_tag_name_table.clearRetainingCapacity(); + f.code_relocs.clearRetainingCapacity(); + f.data_relocs.clearRetainingCapacity(); f.memory_layout_finished = false; } @@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { f.binary_bytes.deinit(gpa); f.missing_exports.deinit(gpa); f.function_imports.deinit(gpa); + f.intrinsic_function_imports.deinit(gpa); + f.function_export_symbols.deinit(gpa); f.global_imports.deinit(gpa); f.data_imports.deinit(gpa); + f.data_exports.deinit(gpa); f.indirect_function_table.deinit(gpa); f.func_types.deinit(gpa); f.enum_tag_name_table.deinit(gpa); + f.code_relocs.deinit(gpa); + f.data_relocs.deinit(gpa); f.* = undefined; } @@ -134,48 +251,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); - // Detect any intrinsics that were called; they need to have dependencies on the symbols marked. - // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized. - for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) { - .call_intrinsic => { - const symbol_name = try wasm.internString(@tagName(data.intrinsic)); - const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(wasm.object_function_imports.getIndex(symbol_name) orelse { - return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{ - data.intrinsic, - }); - })); - try wasm.markFunctionImport(symbol_name, i.value(wasm), i); - log.debug("markFunctionImport intrinsic {d}={t}", .{ i, data.intrinsic }); - }, - .call_tag_index => { - assert(ip.indexToKey(data.ip_index) == .enum_type); - const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index); - if (!gop.found_existing) { - const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu); - gop.value_ptr.* = .{ .tag_name = .{ - .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}), - .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target), - } }; - } - try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {}); - }, - .enum_tag_name_table_ref => { - assert(ip.indexToKey(data.ip_index) == .enum_type); - const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index); - if (!gop.found_existing) { - wasm.tag_name_table_ref_count += 1; - gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len); - const tag_names = ip.loadEnumType(data.ip_index).field_names; - for (tag_names.get(ip)) |tag_name| { - const slice = tag_name.toSlice(ip); - try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); - try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); - } - } - }, - else => continue, - }; - { var i = wasm.function_imports_len_prelink; while (i < f.function_imports.entries.len) { @@ -225,10 +300,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?; const explicit = f.missing_exports.swapRemove(nav_export.name); - const is_hidden = !explicit and switch (export_index.ptr(zcu).opts.visibility) { + const opts = export_index.ptr(zcu).opts; + const is_hidden = !explicit and switch (opts.visibility) { .hidden => true, .default, .protected => false, }; + if (is_obj) try f.function_export_symbols.put(gpa, nav_export.name, .{ + .function_index = function_index, + .flags = .{ + .binding = switch (opts.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = is_hidden, + .exported = !is_hidden, + }, + }); if (is_hidden) { try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index); } else { @@ -239,17 +328,141 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (nav_export.name.toOptional() == entry_name) wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index); } else { - // This is a data export because Zcu currently has no way to - // export wasm globals. - _ = f.missing_exports.swapRemove(nav_export.name); + // data exports are linker symbols + // explicit exports become address globals + const explicit = f.missing_exports.swapRemove(nav_export.name); + const opts = export_index.ptr(zcu).opts; + try f.data_exports.put(gpa, nav_export.name, .{ + .resolution = .fromIpNav(wasm, nav_export.nav_index), + .flags = if (is_obj) .{ + .binding = switch (opts.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = !explicit and switch (opts.visibility) { + .default => false, + .hidden => true, + .protected => false, + }, + .exported = explicit, + .tls = ip.getNav(nav_export.nav_index).resolved.?.@"threadlocal", + } else .{}, + }); _ = f.data_imports.swapRemove(nav_export.name); - if (!is_obj) { - diags.addError("unable to export data symbol '{s}'; not emitting a relocatable", .{ - nav_export.name.slice(wasm), + if (explicit and !is_obj) { + const global_resolution: Wasm.GlobalImport.Resolution = .fromIpNav( + wasm, + nav_export.nav_index, + ); + try wasm.globals.put(gpa, global_resolution, {}); + try wasm.global_exports.append(gpa, .{ + .name = nav_export.name, + .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?, }); } } } + // handle exported values without navs + for (wasm.uav_exports.keys(), wasm.uav_exports.values()) |uav_export, export_index| { + assert(!ip.isFunctionType(ip.typeOf(uav_export.uav_index))); + const explicit = f.missing_exports.swapRemove(uav_export.name); + const opts = export_index.ptr(zcu).opts; + try f.data_exports.put(gpa, uav_export.name, .{ + .resolution = .fromIpIndex(wasm, uav_export.uav_index), + .flags = if (is_obj) .{ + .binding = switch (opts.linkage) { + .internal => .local, + .strong => .strong, + .weak => .weak, + .link_once => @panic("TODO: COMDAT"), + }, + .visibility_hidden = !explicit and switch (opts.visibility) { + .default => false, + .hidden => true, + .protected => false, + }, + .exported = explicit, + } else .{}, + }); + _ = f.data_imports.swapRemove(uav_export.name); + if (explicit and !is_obj) { + const global_resolution: Wasm.GlobalImport.Resolution = .fromIpIndex( + wasm, + uav_export.uav_index, + ); + try wasm.globals.put(gpa, global_resolution, {}); + try wasm.global_exports.append(gpa, .{ + .name = uav_export.name, + .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?, + }); + } + } + + // Detect any intrinsics that were called; they need to have dependencies on the symbols marked. + // Likewise detect `@tagName` calls so those functions can be included in the output and synthesized. + for (wasm.mir_instructions.items(.tag), wasm.mir_instructions.items(.data)) |tag, *data| switch (tag) { + .call_intrinsic => { + const symbol_name = try wasm.internString(@tagName(data.intrinsic)); + if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null and + !f.function_imports.contains(symbol_name)) + { + if (wasm.object_function_imports.getIndex(symbol_name)) |object_import_index| { + const i: Wasm.FunctionImport.Index = @fromBackingInt(@intCast(object_import_index)); + try wasm.markFunctionImport(symbol_name, i.value(wasm), i); + if (Wasm.FunctionIndex.fromSymbolName(wasm, symbol_name) == null) { + try f.function_imports.put(gpa, symbol_name, .fromObject(i, wasm)); + } + } else if (is_obj) { + const gop = try f.intrinsic_function_imports.getOrPut(gpa, symbol_name); + if (!gop.found_existing) gop.value_ptr.* = try wasm.intrinsicFunctionType(data.intrinsic); + } else { + return diags.fail("missing compiler runtime intrinsic '{t}' (undefined linker symbol)", .{ + data.intrinsic, + }); + } + } + }, + .call_indirect => { + const fn_info = zcu.typeToFunc(.fromInterned(data.ip_index)).?; + const type_index = wasm.getExistingFunctionType( + fn_info.cc, + fn_info.param_types.get(ip), + .fromInterned(fn_info.return_type), + fn_info.is_var_args, + target, + ).?; + try f.func_types.put(gpa, type_index, {}); + }, + .call_tag_index => { + assert(ip.indexToKey(data.ip_index) == .enum_type); + const gop = try wasm.zcu_funcs.getOrPut(gpa, data.ip_index); + if (!gop.found_existing) { + const int_tag_ty = Zcu.Type.fromInterned(data.ip_index).backingIntType(zcu); + gop.value_ptr.* = .{ .tag_name = .{ + .symbol_name = try wasm.internStringFmt("__zig_tag_index_{d}", .{data.ip_index}), + .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .u32, false, target), + } }; + } + try wasm.functions.put(gpa, .fromZcuFunc(wasm, @fromBackingInt(@intCast(gop.index))), {}); + }, + .enum_tag_name_table_ref => { + assert(ip.indexToKey(data.ip_index) == .enum_type); + const gop = try f.enum_tag_name_table.getOrPut(gpa, data.ip_index); + if (!gop.found_existing) { + wasm.tag_name_table_ref_count += 1; + gop.value_ptr.* = @intCast(wasm.tag_name_offs.items.len); + const tag_names = ip.loadEnumType(data.ip_index).field_names; + for (tag_names.get(ip)) |tag_name| { + const slice = tag_name.toSlice(ip); + try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); + try wasm.tag_name_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); + } + } + }, + else => continue, + }; for (f.missing_exports.keys()) |exp_name| { diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)}); @@ -300,7 +513,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (wasm.object_init_funcs.items.len > 0) { // Zig has no constructors so these are only for object file inputs. mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan); - try wasm.functions.put(gpa, .__wasm_call_ctors, {}); + if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {}); + } + + if (is_obj) { + try wasm.datas.ensureUnusedCapacity(gpa, wasm.uavs_obj.entries.len + wasm.navs_obj.entries.len + 4); + for (0..wasm.uavs_obj.entries.len) |i| wasm.datas.putAssumeCapacity( + .pack(wasm, .{ .uav_obj = @fromBackingInt(@intCast(i)) }), + {}, + ); + for (0..wasm.navs_obj.entries.len) |i| wasm.datas.putAssumeCapacity( + .pack(wasm, .{ .nav_obj = @fromBackingInt(@intCast(i)) }), + {}, + ); + if (wasm.error_name_table_ref_count > 0) { + wasm.datas.putAssumeCapacity(.__zig_error_names, {}); + wasm.datas.putAssumeCapacity(.__zig_error_name_table, {}); + } + if (wasm.tag_name_table_ref_count > 0) { + wasm.datas.putAssumeCapacity(.__zig_tag_names, {}); + wasm.datas.putAssumeCapacity(.__zig_tag_name_table, {}); + } } // Merge and order the data segments. Depends on garbage collection so that @@ -341,14 +574,33 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // dropped in __wasm_init_memory, which is registered as the start function // We also initialize bss segments (using memory.fill) as part of this // function. - if (wasm.any_passive_inits) { + if (!is_obj and wasm.any_passive_inits) { try wasm.addFunction(.__wasm_init_memory, &.{}, &.{}); } try wasm.tables.ensureUnusedCapacity(gpa, 1); if (f.indirect_function_table.entries.len > 0) { - wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); + if (is_obj) { + const name = wasm.preloaded_strings.__indirect_function_table; + const gop = try wasm.object_table_imports.getOrPut(gpa, name); + if (!gop.found_existing) gop.value_ptr.* = .{ + .flags = .{ + .undefined = true, + .no_strip = true, + }, + .module_name = wasm.preloaded_strings.env, + .name = name, + .source_location = .zig_object_nofile, + .resolution = .unresolved, + .limits_min = 1, + .limits_max = 0, + }; + const import_index: Wasm.TableImport.Index = @fromBackingInt(@intCast(gop.index)); + try wasm.markTableImport(name, gop.value_ptr, import_index); + } else { + wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); + } } // Sort order: @@ -449,7 +701,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const start_addr = alignment.forward(memory_ptr); const want_new_segment = b: { - if (is_obj) break :b false; + if (is_obj) break :b i != 0; switch (seen_tls) { .before => switch (category) { .tls => { @@ -489,7 +741,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) }); memory_ptr = start_addr + size; } - if (category != .zero) try f.data_segment_groups.append(gpa, .{ + if (is_obj or category != .zero) try f.data_segment_groups.append(gpa, .{ .first_segment = first_segment, .end_addr = @intCast(memory_ptr), }); @@ -555,7 +807,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // When we have TLS GOT entries and shared memory is enabled, we must // perform runtime relocations or else we don't create the function. - if (shared_memory and virtual_addrs.tls_base != null) { + if (!is_obj and shared_memory and virtual_addrs.tls_base != null) { // This logic that checks `any_tls_relocs` is missing the part where it // also notices threadlocal globals from Zcu code. if (wasm.any_tls_relocs) try wasm.addFunction(.__wasm_apply_global_tls_relocs, &.{}, &.{}); @@ -582,6 +834,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { for (f.function_imports.values()) |id| { try f.func_types.put(gpa, id.functionType(wasm), {}); } + for (f.intrinsic_function_imports.values()) |type_index| { + try f.func_types.put(gpa, type_index, {}); + } for (wasm.functions.keys()) |function| { try f.func_types.put(gpa, function.typeIndex(wasm), {}); } @@ -617,7 +872,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); for (f.function_imports.values()) |id| { - const module_name = id.moduleName(wasm).slice(wasm).?; + const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm); try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); try binary_bytes.appendSlice(gpa, module_name); @@ -631,6 +886,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } total_imports += f.function_imports.entries.len; + for (f.intrinsic_function_imports.keys(), f.intrinsic_function_imports.values()) |name_string, type_index| { + const module_name = wasm.preloaded_strings.env.slice(wasm); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); + try binary_bytes.appendSlice(gpa, module_name); + + const name = name_string.slice(wasm); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + + try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.function)); + try appendLeb128(gpa, binary_bytes, @backingInt(FuncTypeIndex.fromTypeIndex(type_index, f))); + } + total_imports += f.intrinsic_function_imports.entries.len; + for (wasm.table_imports.values()) |id| { const table_import = id.value(wasm); const module_name = table_import.module_name.slice(wasm); @@ -662,7 +931,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } for (f.global_imports.values()) |id| { - const module_name = id.moduleName(wasm).slice(wasm).?; + const module_name = (id.moduleName(wasm).unwrap() orelse wasm.preloaded_strings.env).slice(wasm); try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); try binary_bytes.appendSlice(gpa, module_name); @@ -726,12 +995,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { for (wasm.globals.keys()) |global_resolution| { switch (global_resolution.unpack(wasm)) { .unresolved => unreachable, - .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base), - .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end), - .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer), - .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)), - .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?), - .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?), + .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base, is64), + .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end, is64), + .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer, is64), + .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?), is64), + .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?, is64), + .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?, is64), .object_global => |i| { const global = i.ptr(wasm); try binary_bytes.appendSlice(gpa, &.{ @@ -740,8 +1009,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { }); try emitExpr(wasm, binary_bytes, global.expr); }, - .nav_exe => unreachable, // Zig source code currently cannot represent this. - .nav_obj => unreachable, // Zig source code currently cannot represent this. + .uav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.uavAddr(i.key(wasm).*), is64), + .nav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.navAddr(i.key(wasm).*), is64), + .uav_obj, .nav_obj => unreachable, } } @@ -766,7 +1036,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (wasm.export_table and f.indirect_function_table.entries.len > 0) { const name = "__indirect_function_table"; - const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); + const index: u32 = @intCast(wasm.table_imports.entries.len + + wasm.tables.getIndex(.__indirect_function_table).?); try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); try binary_bytes.appendSlice(gpa, name); try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table)); @@ -803,8 +1074,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // start section if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); + section_index += 1; } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { try emitStartSection(gpa, binary_bytes, func_index); + section_index += 1; } // element section @@ -812,7 +1085,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); // indirect function table elements - const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); + const table_index: u32 = @intCast( + wasm.table_imports.getIndex(wasm.preloaded_strings.__indirect_function_table) orelse + wasm.table_imports.entries.len + wasm.tables.getIndex(.__indirect_function_table).?, + ); // passive with implicit 0-index table or set table index manually const flags: u32 = if (table_index == 0) 0x0 else 0x02; try appendLeb128(gpa, binary_bytes, flags); @@ -841,11 +1117,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (f.data_segment_groups.items.len > 0) { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len)); + section_index += 1; } // Code section. if (wasm.functions.count() != 0) { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); + const section_offset = binary_bytes.items.len - uleb128size(@intCast(wasm.functions.count())); for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) { .unresolved => unreachable, @@ -870,10 +1148,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const code = ptr.code.slice(wasm); try appendLeb128(gpa, binary_bytes, code.len); const code_start = binary_bytes.items.len; + const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); try binary_bytes.appendSlice(gpa, code); - if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); + if (is_obj) { + try processRelocs( + wasm, + &f.code_relocs, + output_offset, + ptr.offset, + ptr.relocations(wasm), + ); + } else { + applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); + } }, .zcu_func => |i| { + const function_offset: u32 = @intCast(binary_bytes.items.len - section_offset); const code_start = try reserveSize(gpa, binary_bytes); defer replaceSize(binary_bytes, code_start); @@ -899,7 +1189,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { .func_tys = undefined, .error_name_table_ref_count = undefined, }; + const body_start: u32 = @intCast(binary_bytes.items.len); + const relocs_start: u32 = @intCast(wasm.zcu_relocations.len); + defer wasm.zcu_relocations.shrinkRetainingCapacity(relocs_start); try mir.lower(wasm, binary_bytes); + const relocs_len: u32 = @intCast(wasm.zcu_relocations.len - relocs_start); + if (is_obj) { + const body_len: u32 = @intCast(binary_bytes.items.len - @as(usize, body_start)); + const output_offset = function_offset + uleb128size(body_len); + try processZcuRelocs( + wasm, + &f.code_relocs, + output_offset, + body_start, + .{ .off = relocs_start, .len = relocs_len }, + ); + } }, } }, @@ -921,8 +1226,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } } for (wasm.nav_fixups.items) |nav_fixup| { - const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index }); - const vaddr = f.data_segments.get(ds_id).? + nav_fixup.addend; + const vaddr = wasm.navAddr(nav_fixup.nav_index) + nav_fixup.addend; if (!is64) { mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); } else { @@ -930,7 +1234,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } } for (wasm.func_table_fixups.items) |fixup| { - const table_index: IndirectFunctionTableIndex = .fromZcuIndirectFunctionSetIndex(fixup.table_index); + const table_index: IndirectFunctionTableIndex = .fromIpNav(wasm, fixup.nav_index); if (!is64) { mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little); } else { @@ -942,6 +1246,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // Data section. if (f.data_segment_groups.items.len != 0) { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); + const section_offset = binary_bytes.items.len - uleb128size(@intCast(f.data_segment_groups.items.len)); var group_index: u32 = 0; var segment_offset: u32 = 0; @@ -976,7 +1281,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { try appendLeb128(gpa, binary_bytes, group_size); } if (segment_id.isEmpty(wasm)) { - // It counted for virtual memory but it does not go into the binary. + if (is_obj) { + const group_size = group_end_addr - group_start_addr; + try binary_bytes.appendNTimes(gpa, 0, group_size - segment_offset); + segment_offset = group_size; + } continue; } @@ -986,6 +1295,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { segment_offset = needed_offset; const code_start = binary_bytes.items.len; + const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); append: { const code = switch (segment_id.unpack(wasm)) { .__heap_base => { @@ -1001,12 +1311,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { break :append; }, .__zig_error_name_table => { - if (is_obj) @panic("TODO error name table reloc"); - const base = f.data_segments.get(.__zig_error_names).?; - if (!is64) { - try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32); + if (is_obj) { + try emitRelocatableNameTable( + wasm, + binary_bytes, + &f.data_relocs, + output_offset, + wasm.error_name_offs.items, + wasm.error_name_bytes.items, + .__zig_error_names, + ); } else { - try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64); + const base = f.data_segments.get(.__zig_error_names).?; + try emitTagNameTable(wasm, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, is64); } break :append; }, @@ -1015,22 +1332,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { break :append; }, .__zig_tag_name_table => { - if (is_obj) @panic("TODO tag name table reloc"); - const base = f.data_segments.get(.__zig_tag_names).?; - if (!is64) { - try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32); + if (is_obj) { + try emitRelocatableNameTable( + wasm, + binary_bytes, + &f.data_relocs, + output_offset, + wasm.tag_name_offs.items, + wasm.tag_name_bytes.items, + .__zig_tag_names, + ); } else { - try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64); + const base = f.data_segments.get(.__zig_tag_names).?; + try emitTagNameTable(wasm, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, is64); } break :append; }, .object => |i| { const ptr = i.ptr(wasm); try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm)); - if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); + if (is_obj) { + try processRelocs( + wasm, + &f.data_relocs, + output_offset, + ptr.offset, + ptr.relocations(wasm), + ); + } else { + applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); + } break :append; }, - inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code, + inline .uav_obj, .nav_obj => |i| { + const zcu_data = i.value(wasm); + try binary_bytes.appendSlice(gpa, zcu_data.code.slice(wasm)); + try processZcuRelocs( + wasm, + &f.data_relocs, + output_offset, + zcu_data.code.off.unwrap().?, + zcu_data.relocs, + ); + break :append; + }, + inline .uav_exe, .nav_exe => |i| i.value(wasm).code, }; try binary_bytes.appendSlice(gpa, code.slice(wasm)); } @@ -1043,7 +1389,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } if (is_obj) { - @panic("TODO emit link section for object file and emit modified relocations"); + var symbol_table_offsets: SymbolTableOffsets = undefined; + { + const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); + defer writeCustomSectionHeader(binary_bytes, header_offset); + + const linking_name = "linking"; + try appendLeb128(gpa, binary_bytes, @as(u32, linking_name.len)); + try binary_bytes.appendSlice(gpa, linking_name); + + try appendLeb128(gpa, binary_bytes, @as(u32, 2)); + + // WASM_SEGMENT_INFO + { + const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); + defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.segment_info)); + + const total_data_segments: u32 = @intCast(f.data_segment_groups.items.len); + try appendLeb128(gpa, binary_bytes, total_data_segments); + + for (f.data_segment_groups.items) |group| { + const segment = group.first_segment; + const name, _ = splitSegmentName(segment.name(wasm)); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + + try appendLeb128(gpa, binary_bytes, @as(u32, segment.alignment(wasm).toLog2Units())); + + var flags: u32 = 0; + if (segment.isStrings(wasm)) flags |= 1; + if (segment.isTls(wasm)) flags |= 2; + if (segment.isRetain(wasm)) flags |= 4; + try appendLeb128(gpa, binary_bytes, flags); + } + } + + // WASM_SYMBOL_TABLE + { + const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); + defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.symbol_table)); + + const total_symbols: u32 = @intCast( + f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + + wasm.functions.entries.len + + f.function_export_symbols.entries.len + + f.data_imports.entries.len + wasm.datas.entries.len + f.data_exports.entries.len + + f.global_imports.entries.len + wasm.globals.entries.len + + wasm.table_imports.entries.len + wasm.tables.entries.len, + ); + try appendLeb128(gpa, binary_bytes, total_symbols); + var symbol_count: u32 = 0; + + // SYMTAB_FUNCTION + { + symbol_table_offsets.function = symbol_count; + for (f.function_imports.values(), 0..) |i, function_index| { + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); + const flags = i.flags(wasm); + assert(flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); + if (flags.explicit_name) { + unreachable; // never set + } + symbol_count += 1; + } + const intrinsic_flags: Wasm.SymbolFlags = .{ .undefined = true }; + for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |_, function_index| { + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); + try appendLeb128(gpa, binary_bytes, intrinsic_flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); + symbol_count += 1; + } + for ( + wasm.functions.keys(), + f.function_imports.entries.len + f.intrinsic_function_imports.entries.len.., + ) |resolution, function_index| { + const name = resolution.name(wasm).?; + const flags = resolution.flags(wasm); + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); + assert(!flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + symbol_count += 1; + } + for ( + f.function_export_symbols.keys(), + f.function_export_symbols.values(), + ) |name_string, symbol| { + const name = name_string.slice(wasm); + const function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex( + wasm, + symbol.function_index, + ); + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.function)); + try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @backingInt(function_index)); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + symbol_count += 1; + } + } + + // SYMTAB_DATA + { + symbol_table_offsets.data = symbol_count; + for (f.data_imports.keys(), f.data_imports.values()) |name_string, data_index| { + const name = name_string.slice(wasm); + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); + const flags = data_index.flags(wasm); + assert(flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + symbol_count += 1; + } + for (wasm.datas.keys()) |resolution| { + var buf: [32]u8 = undefined; + const name = resolution.name(wasm, &buf); + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); + const flags = resolution.flags(wasm); + assert(!flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + + const data_loc = resolution.dataLoc(wasm); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + + const segment_index = f.data_segments.getIndex(data_loc.segment).?; + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index))); + try appendLeb128(gpa, binary_bytes, data_loc.offset); + try appendLeb128(gpa, binary_bytes, resolution.size(wasm)); + symbol_count += 1; + } + for (f.data_exports.keys(), f.data_exports.values()) |name_string, symbol| { + const name = name_string.slice(wasm); + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.data)); + try appendLeb128(gpa, binary_bytes, symbol.flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + + const data_loc = symbol.resolution.dataLoc(wasm); + const segment_index = f.data_segments.getIndex(data_loc.segment).?; + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_index))); + try appendLeb128(gpa, binary_bytes, data_loc.offset); + try appendLeb128(gpa, binary_bytes, symbol.resolution.size(wasm)); + symbol_count += 1; + } + } + + // SYMTAB_GLOBAL + { + symbol_table_offsets.global = symbol_count; + for (f.global_imports.values(), 0..) |i, global_index| { + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global)); + const flags = i.flags(wasm); + assert(flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); + if (flags.explicit_name) { + unreachable; // never set + } + symbol_count += 1; + } + for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { + var buf: [32]u8 = undefined; + const name = resolution.name(wasm, &buf).?; + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.global)); + const flags = resolution.flags(wasm); + assert(!flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + symbol_count += 1; + } + } + + // SYMTAB_EVENT + { + // TODO not parsed yet + } + + // SYMTAB_SECTION + { + // TODO not parsed correctly yet + } + + // SYMTAB_TABLE + { + symbol_table_offsets.table = symbol_count; + for (wasm.table_imports.values(), 0..) |i, table_index| { + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table)); + const flags = i.value(wasm).flags; + assert(flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index))); + if (flags.explicit_name) { + unreachable; // never set + } + symbol_count += 1; + } + for (wasm.tables.keys(), wasm.table_imports.entries.len..) |resolution, table_index| { + const name = resolution.name(wasm).?; + try binary_bytes.append(gpa, @backingInt(Object.Symbol.Tag.table)); + const flags = resolution.flags(wasm); + assert(!flags.undefined); + try appendLeb128(gpa, binary_bytes, flags.toAbiInteger()); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(table_index))); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + symbol_count += 1; + } + } + assert(symbol_count == total_symbols); + } + + // WASM_INIT_FUNCS + { + const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); + defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs)); + + const init_funcs = wasm.object_init_funcs.items; + const total_functions: u32 = b: { + var cnt: u32 = 0; + for (init_funcs) |init_func| { + const func = init_func.function_index.ptr(wasm); + if (!func.object_index.ptr(wasm).is_included) continue; + cnt += 1; + } + break :b cnt; + }; + try appendLeb128(gpa, binary_bytes, total_functions); + + for (init_funcs) |init_func| { + const func = init_func.function_index.ptr(wasm); + if (!func.object_index.ptr(wasm).is_included) continue; + + try appendLeb128(gpa, binary_bytes, init_func.priority); + const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index); + const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index); + try appendLeb128(gpa, binary_bytes, symbol_index); + } + } + + // WASM_COMDAT_INFO + { + // TODO + } + } + + if (f.code_relocs.items.len != 0) try emitRelocSection( + wasm, + binary_bytes, + code_section_index.?, + "reloc.CODE", + f.code_relocs.items, + symbol_table_offsets, + ); + if (f.data_relocs.items.len != 0) try emitRelocSection( + wasm, + binary_bytes, + data_section_index.?, + "reloc.DATA", + f.data_relocs.items, + symbol_table_offsets, + ); } else if (comp.config.debug_format != .strip) { try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes); } @@ -1121,7 +1734,10 @@ fn emitNameSection( const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function)); - const total_functions: u32 = @intCast(f.function_imports.entries.len + wasm.functions.entries.len); + const total_functions: u32 = @intCast( + f.function_imports.entries.len + f.intrinsic_function_imports.entries.len + + wasm.functions.entries.len, + ); try appendLeb128(gpa, binary_bytes, total_functions); for (f.function_imports.keys(), 0..) |name_index, function_index| { @@ -1130,7 +1746,16 @@ fn emitNameSection( try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); try binary_bytes.appendSlice(gpa, name); } - for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| { + for (f.intrinsic_function_imports.keys(), f.function_imports.entries.len..) |name_index, function_index| { + const name = name_index.slice(wasm); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); + try binary_bytes.appendSlice(gpa, name); + } + for ( + wasm.functions.keys(), + f.function_imports.entries.len + f.intrinsic_function_imports.entries.len.., + ) |resolution, function_index| { const name = resolution.name(wasm).?; try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); @@ -1152,7 +1777,8 @@ fn emitNameSection( try binary_bytes.appendSlice(gpa, name); } for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { - const name = resolution.name(wasm).?; + var buf: [32]u8 = undefined; + const name = resolution.name(wasm, &buf).?; try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); try binary_bytes.appendSlice(gpa, name); @@ -1418,29 +2044,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode } -fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.array_list.Managed(u8)) !void { - const gpa = wasm.base.comp.gpa; - try appendLeb128(gpa, binary_bytes, @backingInt(Wasm.SubsectionType.segment_info)); - const segment_offset = binary_bytes.items.len; - - try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(wasm.segment_info.count()))); - for (wasm.segment_info.values()) |segment_info| { - log.debug("Emit segment: {s} align({d}) flags({b})", .{ - segment_info.name, - segment_info.alignment, - segment_info.flags, - }); - try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_info.name.len))); - try binary_bytes.appendSlice(gpa, segment_info.name); - try appendLeb128(gpa, binary_bytes, segment_info.alignment.toLog2Units()); - try appendLeb128(gpa, binary_bytes, segment_info.flags); - } - - var buf: [5]u8 = undefined; - leb.writeUnsignedFixed(5, &buf, @as(u32, @intCast(binary_bytes.items.len - segment_offset))); - try binary_bytes.insertSlice(segment_offset, &buf); -} - fn uleb128size(x: u32) u32 { var value = x; var size: u32 = 0; @@ -1449,22 +2052,395 @@ fn uleb128size(x: u32) u32 { } fn emitTagNameTable( - gpa: Allocator, + wasm: *const Wasm, code: *ArrayList(u8), tag_name_offs: []const u32, tag_name_bytes: []const u8, base: u32, - comptime Int: type, + is64: bool, ) error{OutOfMemory}!void { - const ptr_size_bytes = @divExact(@bitSizeOf(Int), 8); + const gpa = wasm.base.comp.gpa; + const ptr_size_bytes: usize = if (is64) 8 else 4; try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len); for (tag_name_offs) |off| { const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?); - mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little); - mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little); + if (is64) { + mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), base + off, .little); + mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), name_len, .little); + } else { + mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), base + off, .little); + mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little); + } } } +fn emitRelocatableNameTable( + wasm: *const Wasm, + code: *ArrayList(u8), + relocs: *ArrayList(Relocation), + output_offset: u32, + name_offs: []const u32, + name_bytes: []const u8, + names_resolution: Wasm.ObjectDataImport.Resolution, +) error{OutOfMemory}!void { + const gpa = wasm.base.comp.gpa; + const ptr_size = @divExact(wasm.base.comp.root_mod.resolved_target.result.ptrBitWidth(), 8); + const table_start = code.items.len; + const data_index: DataSymbolIndex = .fromResolution(wasm, names_resolution); + try code.ensureUnusedCapacity(gpa, @as(usize, ptr_size) * 2 * name_offs.len); + try relocs.ensureUnusedCapacity(gpa, name_offs.len); + for (name_offs) |off| { + const name_len: u32 = @intCast(mem.indexOfScalar(u8, name_bytes[off..], 0).?); + const reloc_offset = output_offset + @as(u32, @intCast(code.items.len - table_start)); + switch (ptr_size) { + 4 => { + @memset(code.addManyAsArrayAssumeCapacity(4), 0); + mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little); + }, + 8 => { + @memset(code.addManyAsArrayAssumeCapacity(8), 0); + mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), @intCast(name_len), .little); + }, + else => unreachable, + } + relocs.appendAssumeCapacity(.{ + .tag = if (ptr_size == 4) .memory_addr_i32 else .memory_addr_i64, + .offset = reloc_offset, + .pointee = .{ .data = data_index }, + .addend = @intCast(off), + }); + } +} + +fn emitRelocSection( + wasm: *const Wasm, + binary_bytes: *ArrayList(u8), + section_index: u32, + reloc_name: []const u8, + relocs: []const Relocation, + symbol_table_offsets: SymbolTableOffsets, +) !void { + const comp = wasm.base.comp; + const gpa = comp.gpa; + + const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); + defer writeCustomSectionHeader(binary_bytes, header_offset); + + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(reloc_name.len))); + try binary_bytes.appendSlice(gpa, reloc_name); + + try appendLeb128(gpa, binary_bytes, section_index); + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(relocs.len))); + + for (relocs) |r| { + try binary_bytes.append(gpa, @backingInt(r.tag)); + try appendLeb128(gpa, binary_bytes, r.offset); + switch (r.tag) { + .memory_addr_leb, + .memory_addr_sleb, + .memory_addr_i32, + .memory_addr_rel_sleb, + .memory_addr_leb64, + .memory_addr_sleb64, + .memory_addr_i64, + .memory_addr_rel_sleb64, + .memory_addr_tls_sleb, + .memory_addr_locrel_i32, + .memory_addr_tls_sleb64, + => { + const symbol_index: u32 = symbol_table_offsets.data + @backingInt(r.pointee.data); + try appendLeb128(gpa, binary_bytes, symbol_index); + }, + .section_offset_i32 => { + @panic("TODO"); + }, + .type_index_leb => { + try appendLeb128(gpa, binary_bytes, @backingInt(r.pointee.type_index)); + }, + .function_offset_i32, + .function_offset_i64, + .function_index_leb, + .function_index_i32, + .table_index_sleb, + .table_index_i32, + .table_index_sleb64, + .table_index_i64, + .table_index_rel_sleb, + .table_index_rel_sleb64, + => { + const symbol_index: u32 = symbol_table_offsets.function + @backingInt(r.pointee.function); + try appendLeb128(gpa, binary_bytes, symbol_index); + }, + .global_index_leb, .global_index_i32 => { + const symbol_index: u32 = symbol_table_offsets.global + @backingInt(r.pointee.global); + try appendLeb128(gpa, binary_bytes, symbol_index); + }, + .table_number_leb => { + const symbol_index: u32 = symbol_table_offsets.table + @backingInt(r.pointee.table); + try appendLeb128(gpa, binary_bytes, symbol_index); + }, + .event_index_leb => @panic("TODO"), + } + switch (r.tag) { + .memory_addr_leb, + .memory_addr_sleb, + .memory_addr_i32, + .memory_addr_rel_sleb, + .memory_addr_leb64, + .memory_addr_sleb64, + .memory_addr_i64, + .memory_addr_rel_sleb64, + .memory_addr_tls_sleb, + .memory_addr_locrel_i32, + .memory_addr_tls_sleb64, + .function_offset_i32, + .function_offset_i64, + .section_offset_i32, + => { + try appendLeb128(gpa, binary_bytes, r.addend); + }, + else => {}, + } + } +} + +fn processZcuRelocs( + wasm: *const Wasm, + out: *ArrayList(Relocation), + output_offset: u32, + input_offset: u32, + relocs: Wasm.ZcuRelocation.Slice, +) !void { + const gpa = wasm.base.comp.gpa; + for ( + relocs.tags(wasm), + relocs.pointees(wasm), + relocs.offsets(wasm), + relocs.addends(wasm), + ) |tag, pointee, offset, addend| { + const output_pointee: Relocation.Pointee = switch (pointee) { + .function_nav => |nav_index| .{ .function = .fromIpNav(wasm, nav_index) }, + .function_name => |name| .{ .function = .fromSymbolName(wasm, name) }, + .tag_function => |ip_index| .{ .function = .fromTagIndexType(wasm, ip_index) }, + .data_uav => |ip_index| .{ .data = .fromUav(wasm, ip_index) }, + .data_nav => |nav_index| .{ .data = .fromNav(wasm, nav_index) }, + .data_resolution => |resolution| .{ .data = .fromResolution(wasm, resolution) }, + .stack_pointer => .{ .global = .fromSymbolName(wasm, wasm.preloaded_strings.__stack_pointer) }, + .type_index => |type_index| .{ .type_index = .fromTypeIndex(type_index, &wasm.flush_buffer) }, + }; + try out.append(gpa, .{ + .tag = tag, + .offset = output_offset + (offset - input_offset), + .pointee = output_pointee, + .addend = addend, + }); + } +} + +fn processRelocs( + wasm: *const Wasm, + out: *ArrayList(Relocation), + output_offset: u32, + input_offset: u32, + relocs: Wasm.ObjectRelocation.IterableSlice, +) !void { + const gpa = wasm.base.comp.gpa; + for ( + relocs.slice.tags(wasm), + relocs.slice.pointees(wasm), + relocs.slice.offsets(wasm), + relocs.slice.addends(wasm), + ) |tag, pointee, offset, addend| { + if (offset >= relocs.end) break; + const rebased_offset = output_offset + (offset - input_offset); + try out.ensureUnusedCapacity(gpa, 1); + switch (tag) { + .function_index_i32 => out.appendAssumeCapacity(.{ + .tag = .function_index_i32, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + .function_index_leb => out.appendAssumeCapacity(.{ + .tag = .function_index_leb, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + .function_offset_i32 => @panic("TODO this value is not known yet"), + .function_offset_i64 => @panic("TODO this value is not known yet"), + .table_index_i32 => out.appendAssumeCapacity(.{ + .tag = .table_index_i32, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + .table_index_i64 => out.appendAssumeCapacity(.{ + .tag = .table_index_i64, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + .table_index_rel_sleb => @panic("TODO what does this reloc tag mean?"), + .table_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"), + .table_index_sleb => out.appendAssumeCapacity(.{ + .tag = .table_index_sleb, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + .table_index_sleb64 => out.appendAssumeCapacity(.{ + .tag = .table_index_sleb64, + .offset = rebased_offset, + .pointee = .{ .function = .fromObjectFunctionHandlingWeak(wasm, pointee.function) }, + .addend = addend, + }), + + .function_import_index_i32 => out.appendAssumeCapacity(.{ + .tag = .function_index_i32, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .function_import_index_leb => out.appendAssumeCapacity(.{ + .tag = .function_index_leb, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .function_import_offset_i32 => @panic("TODO this value is not known yet"), + .function_import_offset_i64 => @panic("TODO this value is not known yet"), + .table_import_index_i32 => out.appendAssumeCapacity(.{ + .tag = .table_index_i32, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .table_import_index_i64 => out.appendAssumeCapacity(.{ + .tag = .table_index_i64, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .table_import_index_rel_sleb => @panic("TODO what does this reloc tag mean?"), + .table_import_index_rel_sleb64 => @panic("TODO what does this reloc tag mean?"), + .table_import_index_sleb => out.appendAssumeCapacity(.{ + .tag = .table_index_sleb, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .table_import_index_sleb64 => out.appendAssumeCapacity(.{ + .tag = .table_index_sleb64, + .offset = rebased_offset, + .pointee = .{ .function = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + + .global_index_i32 => out.appendAssumeCapacity(.{ + .tag = .global_index_i32, + .offset = rebased_offset, + .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) }, + .addend = addend, + }), + .global_index_leb => out.appendAssumeCapacity(.{ + .tag = .global_index_leb, + .offset = rebased_offset, + .pointee = .{ .global = .fromObjectGlobalHandlingWeak(wasm, pointee.global) }, + .addend = addend, + }), + + .global_import_index_i32 => out.appendAssumeCapacity(.{ + .tag = .global_index_i32, + .offset = rebased_offset, + .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .global_import_index_leb => out.appendAssumeCapacity(.{ + .tag = .global_index_leb, + .offset = rebased_offset, + .pointee = .{ .global = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + + .memory_addr_i32, + .memory_addr_i64, + .memory_addr_leb, + .memory_addr_leb64, + .memory_addr_sleb, + .memory_addr_sleb64, + .memory_addr_tls_sleb, + .memory_addr_tls_sleb64, + => out.appendAssumeCapacity(.{ + .tag = memoryRelocationType(tag), + .offset = rebased_offset, + .pointee = .{ .data = .fromObjectData(wasm, pointee.data) }, + .addend = addend, + }), + .memory_addr_locrel_i32 => @panic("TODO implement relocation memory_addr_locrel_i32"), + .memory_addr_rel_sleb => @panic("TODO implement relocation memory_addr_rel_sleb"), + .memory_addr_rel_sleb64 => @panic("TODO implement relocation memory_addr_rel_sleb64"), + + .memory_addr_import_i32, + .memory_addr_import_i64, + .memory_addr_import_leb, + .memory_addr_import_leb64, + .memory_addr_import_sleb, + .memory_addr_import_sleb64, + => out.appendAssumeCapacity(.{ + .tag = memoryRelocationType(tag), + .offset = rebased_offset, + .pointee = .{ .data = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + .memory_addr_import_locrel_i32 => @panic("TODO implement relocation memory_addr_import_locrel_i32"), + .memory_addr_import_rel_sleb => @panic("TODO implement relocation memory_addr_import_rel_sleb"), + .memory_addr_import_rel_sleb64 => @panic("TODO implement memory_addr_import_rel_sleb64"), + .memory_addr_import_tls_sleb => @panic("TODO"), + .memory_addr_import_tls_sleb64 => @panic("TODO"), + + .section_offset_i32 => @panic("TODO this value is not known yet"), + + .table_number_leb => out.appendAssumeCapacity(.{ + .tag = .table_number_leb, + .offset = rebased_offset, + .pointee = .{ .table = .fromObjectTable(wasm, pointee.table) }, + .addend = addend, + }), + .table_import_number_leb => out.appendAssumeCapacity(.{ + .tag = .table_number_leb, + .offset = rebased_offset, + .pointee = .{ .table = .fromSymbolName(wasm, pointee.symbol_name) }, + .addend = addend, + }), + + .type_index_leb => out.appendAssumeCapacity(.{ + .tag = .type_index_leb, + .offset = rebased_offset, + .pointee = .{ .type_index = .fromTypeIndex(pointee.type_index, &wasm.flush_buffer) }, + .addend = addend, + }), + } + } +} + +fn memoryRelocationType(tag: Wasm.ObjectRelocation.Tag) Object.RelocationType { + return switch (tag) { + .memory_addr_i32, .memory_addr_import_i32 => .memory_addr_i32, + .memory_addr_i64, .memory_addr_import_i64 => .memory_addr_i64, + .memory_addr_leb, .memory_addr_import_leb => .memory_addr_leb, + .memory_addr_leb64, .memory_addr_import_leb64 => .memory_addr_leb64, + .memory_addr_locrel_i32, .memory_addr_import_locrel_i32 => .memory_addr_locrel_i32, + .memory_addr_rel_sleb, .memory_addr_import_rel_sleb => .memory_addr_rel_sleb, + .memory_addr_rel_sleb64, .memory_addr_import_rel_sleb64 => .memory_addr_rel_sleb64, + .memory_addr_sleb, .memory_addr_import_sleb => .memory_addr_sleb, + .memory_addr_sleb64, .memory_addr_import_sleb64 => .memory_addr_sleb64, + .memory_addr_tls_sleb, .memory_addr_import_tls_sleb => .memory_addr_tls_sleb, + .memory_addr_tls_sleb64, .memory_addr_import_tls_sleb64 => .memory_addr_tls_sleb64, + else => unreachable, + }; +} + fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void { for ( relocs.slice.tags(wasm), @@ -1579,12 +2555,17 @@ const RelocAddr = struct { fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr { const flush = &wasm.flush_buffer; if (wasm.object_data_imports.getPtr(name)) |import| { - return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); - } else if (wasm.data_imports.get(name)) |id| { + if (import.resolution != .unresolved) { + return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); + } + } + if (flush.data_exports.get(name)) |symbol| { + return fromDataLoc(flush, symbol.resolution.dataLoc(wasm), addend); + } + if (wasm.data_imports.get(name)) |id| { return fromDataLoc(flush, .fromDataImportId(wasm, id), addend); - } else { - unreachable; } + unreachable; } fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr { @@ -1702,13 +2683,11 @@ fn emitInitMemoryFunction( } const segment_groups = wasm.flush_buffer.data_segment_groups.items; - var prev_end: u32 = 0; for (segment_groups, 0..) |group, segment_index| { - defer prev_end = group.end_addr; const segment = group.first_segment; if (!segment.isPassive(wasm)) continue; - const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end)); + const start_addr = wasm.flush_buffer.data_segments.get(segment).?; const segment_size: u32 = group.end_addr - start_addr; try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1); @@ -2028,11 +3007,15 @@ fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void { }; } -fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void { - try bytes.ensureUnusedCapacity(gpa, 9); - bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32)); +fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u64, is64: bool) Allocator.Error!void { + try bytes.ensureUnusedCapacity(gpa, if (is64) 14 else 9); + bytes.appendAssumeCapacity(@backingInt(@as(std.wasm.Valtype, if (is64) .i64 else .i32))); bytes.appendAssumeCapacity(mutable); - appendReservedI32Const(bytes, val); + if (is64) { + appendReservedI64Const(bytes, val); + } else { + appendReservedI32Const(bytes, @intCast(val)); + } bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index a9b5a1fe42a27b160b833b9854468ebbba419c17..44359b315bdec094029d9ceed782f798ea32f25f 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -146,7 +146,7 @@ pub const Symbol = struct { pointee: Pointee, /// https://github.com/WebAssembly/tool-conventions/blob/df8d737539eb8a8f446ba5eab9dc670c40dfb81e/Linking.md#symbol-table-subsection - const Tag = enum(u8) { + pub const Tag = enum(u8) { function, data, global, diff --git a/src/target.zig b/src/target.zig index b4dc16b3185bb4e60ec99d93e2a39595f815eeed..82728f3942f07da8fe6d64c922c69a91e8e7ae66 100644 --- a/src/target.zig +++ b/src/target.zig @@ -437,7 +437,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl else => {}, } return switch (zigBackend(target, false)) { - .stage2_aarch64, .stage2_x86_64 => .yes, + .stage2_aarch64, .stage2_wasm, .stage2_x86_64 => .yes, else => .llvm_only, }; } diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d1acfb366dbfe0620409a81ef565b0902237a81b..42c85b0487e2d024adf394300c165feaa126d325 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -797,7 +797,6 @@ test "auto created variables have correct alignment" { } test "extern variable with non-pointer opaque type" { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO diff --git a/test/behavior/builtin_functions_returning_void_or_noreturn.zig b/test/behavior/builtin_functions_returning_void_or_noreturn.zig index cd3bc58de61600a0ad57d745355b5b707b4e5322..820a920464c77e42b6130b5d96838d7eda7a3d9a 100644 --- a/test/behavior/builtin_functions_returning_void_or_noreturn.zig +++ b/test/behavior/builtin_functions_returning_void_or_noreturn.zig @@ -6,7 +6,6 @@ var x: u8 = 1; // This excludes builtin functions that return void or noreturn that cannot be tested. test { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/call.zig b/test/behavior/call.zig index 94e19e723d60cb8cdf2f5cfc1aaa7306ec7bbd81..5f2b24b6b72eadd8dfffa6998ee996e292ed381c 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -21,7 +21,6 @@ test "super basic invocations" { test "basic invocations" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/export_builtin.zig b/test/behavior/export_builtin.zig index 16fc0a7a79c20795b81abf4282c00cf7e1c54258..0381e9645488d4565a56c16630c9e937e152df61 100644 --- a/test/behavior/export_builtin.zig +++ b/test/behavior/export_builtin.zig @@ -5,11 +5,6 @@ const expect = std.testing.expect; test "exporting enum value" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.cpu.arch.isWasm()) { - // https://github.com/ziglang/zig/issues/4866 - return error.SkipZigTest; - } - const S = struct { const E = enum(c_int) { one, two }; const e: E = .two; @@ -35,11 +30,6 @@ test "exporting with internal linkage" { test "exporting using namespace access" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.cpu.arch.isWasm()) { - // https://github.com/ziglang/zig/issues/4866 - return error.SkipZigTest; - } - const S = struct { const Inner = struct { const x: u32 = 5; @@ -57,11 +47,6 @@ test "exporting comptime-known value" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.cpu.arch.isWasm()) { - // https://github.com/ziglang/zig/issues/4866 - return error.SkipZigTest; - } - const x: u32 = 10; @export(&x, .{ .name = "exporting_comptime_known_value_foo" }); const S = struct { diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 47e6be86bb715f90bae1eb08a9237af2f07c1515..69b32ca20271f8bbdf660eb5cc8039c6e0a5bfb1 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -418,7 +418,6 @@ test "import passed byref to function in return type" { test "implicit cast function to function ptr" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S1 = struct { diff --git a/test/tests.zig b/test/tests.zig index d823d2add16c8a4486decb3671025cd60cbc16e2..390154d8fc4cd3f1a9b30fdba87da448d6cbd0e0 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1568,7 +1568,6 @@ const module_test_targets = blk: { .os_tag = .wasi, .abi = .none, }, - .skip_modules = &.{"compiler-rt"}, .use_llvm = false, .use_lld = false, }, -- 2.54.0 From bdb1e9c9cf97520e41c8aff94553d5140a79dac7 Mon Sep 17 00:00:00 2001 From: Pavel Verigo Date: Tue, 28 Jul 2026 23:58:06 +0200 Subject: [PATCH 069/215] wasm: linker update names after compilerrt renames --- src/link/Wasm.zig | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 6ec027ad7f64991b38266e16ad04ee35d66ab14b..352448fd38a62533f708e3be5331cdf96aa91fa5 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4612,48 +4612,48 @@ pub fn intrinsicFunctionType(wasm: *Wasm, intrinsic: Mir.Intrinsic) Allocator.Er .__udivti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), .__umodei5 => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type, .usize_type, .usize_type }, .void), .__umodti3 => internIntrinsicType(wasm, &.{ .u128_type, .u128_type }, .u128), - .ceilq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .ceilf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .cos => internIntrinsicType(wasm, &.{.f64_type}, .f64), .cosf => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .cosq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .cosf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .exp => internIntrinsicType(wasm, &.{.f64_type}, .f64), .exp2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), .exp2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .exp2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .exp2f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .expf => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .expq => internIntrinsicType(wasm, &.{.f128_type}, .f128), - .fabsq => internIntrinsicType(wasm, &.{.f128_type}, .f128), - .floorq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .expf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .fabsf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .floorf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .fma => internIntrinsicType(wasm, &.{ .f64_type, .f64_type, .f64_type }, .f64), .fmaf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type, .f32_type }, .f32), - .fmaq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type, .f128_type }, .f128), + .fmaf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type, .f128_type }, .f128), .fmax => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), .fmaxf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), - .fmaxq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .fmaxf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), .fmin => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), .fminf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), - .fminq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .fminf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), .fmod => internIntrinsicType(wasm, &.{ .f64_type, .f64_type }, .f64), .fmodf => internIntrinsicType(wasm, &.{ .f32_type, .f32_type }, .f32), - .fmodq => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), + .fmodf128 => internIntrinsicType(wasm, &.{ .f128_type, .f128_type }, .f128), .log => internIntrinsicType(wasm, &.{.f64_type}, .f64), .log10 => internIntrinsicType(wasm, &.{.f64_type}, .f64), .log10f => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .log10q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .log10f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .log2 => internIntrinsicType(wasm, &.{.f64_type}, .f64), .log2f => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .log2q => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .log2f128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .logf => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .logq => internIntrinsicType(wasm, &.{.f128_type}, .f128), - .roundq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .logf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .roundf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .sin => internIntrinsicType(wasm, &.{.f64_type}, .f64), .sinf => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .sinq => internIntrinsicType(wasm, &.{.f128_type}, .f128), - .sqrtq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .sinf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .sqrtf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .tan => internIntrinsicType(wasm, &.{.f64_type}, .f64), .tanf => internIntrinsicType(wasm, &.{.f32_type}, .f32), - .tanq => internIntrinsicType(wasm, &.{.f128_type}, .f128), - .truncq => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .tanf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), + .truncf128 => internIntrinsicType(wasm, &.{.f128_type}, .f128), .memcpy => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), .memmove => internIntrinsicType(wasm, &.{ .usize_type, .usize_type, .usize_type }, .usize), .memset => internIntrinsicType(wasm, &.{ .usize_type, .i32_type, .usize_type }, .usize), -- 2.54.0 From bb296ab9b9752893eb362ed951c4ce344214eb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20IRMAK?= Date: Sun, 26 Jul 2026 11:16:51 +0300 Subject: [PATCH 070/215] Add and lower preserve_none call convention for x86_64 & aarch64 std declarations, llvm lowering, c_abi test, compiler warning test Co-authored-by: yarn --- lib/std/Target.zig | 2 ++ lib/std/lang.zig | 2 ++ lib/std/zig/llvm/Builder.zig | 2 ++ src/Zcu.zig | 2 ++ src/codegen/c/type.zig | 6 +++++ src/codegen/llvm.zig | 2 ++ src/link/Dwarf.zig | 2 ++ test/c_abi/cfuncs.c | 10 +++++++++ test/c_abi/main.zig | 22 +++++++++++++++++++ ..._preserve_none_on_unsupported_platform.zig | 16 ++++++++++++++ 10 files changed, 66 insertions(+) create mode 100644 test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 2f395dc0f03d6aa5673df31b4aa3bb92d66bf50a..8ad977e5a528583032f075fb84b5c72fcc504d54 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1793,6 +1793,7 @@ pub const Cpu = struct { .x86_64_regcall_v4_win, .x86_64_vectorcall, .x86_64_interrupt, + .x86_64_preserve_none, => &.{.x86_64}, .x86_sysv, @@ -1819,6 +1820,7 @@ pub const Cpu = struct { .aarch64_aapcs_win, .aarch64_vfabi, .aarch64_vfabi_sve, + .aarch64_preserve_none, => &.{ .aarch64, .aarch64_be }, .alpha_osf, diff --git a/lib/std/lang.zig b/lib/std/lang.zig index f15f26d9f9330431846e52ff9d98b131fbc666e2..c5ff616dc563537fc7016535e07872e9d657362b 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -210,6 +210,7 @@ pub const CallingConvention = union(enum(u8)) { x86_64_regcall_v4_win: CommonOptions, x86_64_vectorcall: CommonOptions, x86_64_interrupt: CommonOptions, + x86_64_preserve_none: CommonOptions, // Calling conventions for the `x86` architecture. x86_sysv: X86RegparmOptions, @@ -237,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) { aarch64_aapcs_win: CommonOptions, aarch64_vfabi: CommonOptions, aarch64_vfabi_sve: CommonOptions, + aarch64_preserve_none: CommonOptions, /// The standard `alpha` calling convention. alpha_osf: CommonOptions, diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 8b9e87f8139f951b7abc475c5afb3035176cb209..9016796a73b0f98f2ded17ef132ea9b4466140ca 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -2749,6 +2749,7 @@ pub const CallConv = enum(u10) { tailcc, cfguard_checkcc, swifttailcc, + preserve_nonecc, x86_stdcallcc = 64, x86_fastcallcc, @@ -2817,6 +2818,7 @@ pub const CallConv = enum(u10) { .tailcc, .cfguard_checkcc, .swifttailcc, + .preserve_nonecc, .x86_stdcallcc, .x86_fastcallcc, .arm_apcscc, diff --git a/src/Zcu.zig b/src/Zcu.zig index 875ffd44b29c92738f12e3cf32f300301edf2d7d..9ed2ed7dc708d3939a1baf479fdd11798415e6fb 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4602,6 +4602,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_64_regcall_v3_sysv, .x86_64_regcall_v4_win, .x86_64_interrupt, + .x86_64_preserve_none, .x86_fastcall, .x86_thiscall, .x86_vectorcall, @@ -4610,6 +4611,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_interrupt, .aarch64_vfabi, .aarch64_vfabi_sve, + .aarch64_preserve_none, .arm_aapcs, .csky_interrupt, .riscv64_lp64_v, diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 347dc7e16e27dce1c3dd41b006f860f5772fce6c..01b474dc9c7cfa2c995cae0f3e75b238b8447619 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -62,6 +62,8 @@ pub const CType = union(enum) { regcall, + preserve_none, + aarch64_vector_pcs, aarch64_sve_pcs, @@ -138,6 +140,10 @@ pub const CType = union(enum) { .x86_regcall_v4_win, => .regcall, + .x86_64_preserve_none, + .aarch64_preserve_none, + => .preserve_none, + .aarch64_vfabi => .aarch64_vector_pcs, .aarch64_vfabi_sve => .aarch64_sve_pcs, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 31e67026821a109d79a6e677014fa0bcf8712615..9e9b32eeab4c25e5d01ecc9bd3fdd80c5703c704 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4558,6 +4558,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const null, .x86_64_vectorcall => .x86_vectorcallcc, .x86_64_interrupt => .x86_intrcc, + .x86_64_preserve_none => .preserve_nonecc, .x86_stdcall => .x86_stdcallcc, .x86_fastcall => .x86_fastcallcc, .x86_thiscall => .x86_thiscallcc, @@ -4573,6 +4574,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const .x86_interrupt => .x86_intrcc, .aarch64_vfabi => .aarch64_vector_pcs, .aarch64_vfabi_sve => .aarch64_sve_vector_pcs, + .aarch64_preserve_none => .preserve_nonecc, .arm_aapcs => .arm_aapcscc, .arm_aapcs_vfp => .arm_aapcs_vfpcc, .riscv64_lp64_v => .riscv_vectorcallcc, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 52d0fc57a1d5238ac2fd837d10878083a94510c7..c8eef4c8651367edbc1abffcd3cf24d76b847603 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4152,6 +4152,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .x86_64_regcall_v4_win => .LLVM_X86RegCall, .x86_64_vectorcall => .LLVM_vectorcall, .x86_sysv, .x86_win, .x86_mingw => .normal, + .x86_64_preserve_none => .LLVM_PreserveNone, .x86_stdcall => .BORLAND_stdcall, .x86_fastcall => .BORLAND_msfastcall, .x86_thiscall => .BORLAND_thiscall, @@ -4165,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .aarch64_aapcs_win => .normal, .aarch64_vfabi => .LLVM_AAPCS, .aarch64_vfabi_sve => .LLVM_AAPCS, + .aarch64_preserve_none => .LLVM_PreserveNone, .arm_aapcs => .LLVM_AAPCS, .arm_aapcs_vfp => .LLVM_AAPCS_VFP, diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index a1471283bfbc5ce35b9bdd4edd6e6cb6df81d831..b74ea9ffef180944eb00c919dd5a6513fa6d32ad 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -16488,6 +16488,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) { } #endif +#if defined __x86_64__ || defined __aarch64__ +int __attribute__((preserve_none)) c_preserve_none(int x) { + return x + 1; +} +int __attribute__((preserve_none)) zig_preserve_none(int); +void c_preserve_none_check(void) { + assert_or_panic(zig_preserve_none(41) == 42); +} +#endif + struct byval_tail_callsite_attr_Point { double x; double y; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 16b99134cf70bc44a77179f48c68704d7a9041ec..a80bacd7ae3d5659902e670ebd38386ecd8c0928 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -17798,3 +17798,25 @@ test "win64 varargs" { @as(Opv, .{}), ); } + +const preserve_none_cc: ?std.lang.CallingConvention = if (builtin.zig_backend != .stage2_llvm) + null +else switch (builtin.cpu.arch) { + .x86_64 => .{ .x86_64_preserve_none = .{} }, + .aarch64, .aarch64_be => .{ .aarch64_preserve_none = .{} }, + else => null, +}; + +export fn zig_preserve_none(x: i32) callconv(preserve_none_cc orelse .c) i32 { + return x + 1; +} + +test "preserve_none calling convention" { + if (preserve_none_cc == null) return error.SkipZigTest; + const static = struct { + extern fn c_preserve_none(x: i32) callconv(preserve_none_cc.?) i32; + extern fn c_preserve_none_check() void; + }; + try expect(static.c_preserve_none(41) == 42); + static.c_preserve_none_check(); +} diff --git a/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig new file mode 100644 index 0000000000000000000000000000000000000000..3997609595403f793e1aae1ac0f5c935e320a5c7 --- /dev/null +++ b/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig @@ -0,0 +1,16 @@ +const F1 = fn () callconv(.{ .x86_64_preserve_none = .{} }) void; +const F2 = fn () callconv(.{ .aarch64_preserve_none = .{} }) void; +export fn entry1() void { + const a: F1 = undefined; + _ = a; +} +export fn entry2() void { + const a: F2 = undefined; + _ = a; +} + +// error +// target=riscv64-linux-none +// +// :1:28: error: calling convention 'x86_64_preserve_none' only available on architectures 'x86_64' +// :2:28: error: calling convention 'aarch64_preserve_none' only available on architectures 'aarch64', 'aarch64_be' -- 2.54.0 From d58883cd535f1623c6e0e9b025f1da1fb6672955 Mon Sep 17 00:00:00 2001 From: Dmitry Mostovenko Date: Thu, 30 Jul 2026 01:08:58 +0300 Subject: [PATCH 071/215] langref: errdefer capture doc remove --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 9be898fc0499bc091f9020bd053ad3f4a2a1e851..9a19c4d95d7fed570085253b090d20ee43d1edf4 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7499,7 +7499,7 @@ fn readU32Be() u32 {}

{#syntax#}errdefer{#endsyntax#}
- {#syntax#}errdefer{#endsyntax#} will execute an expression when control flow leaves the current block if the function returns an error, the errdefer expression can capture the unwrapped value. + {#syntax#}errdefer{#endsyntax#} will execute an expression when control flow leaves the current block if the function returns an error.
  • See also {#link|errdefer#}
-- 2.54.0 From 7ad63f2e5bf3d93e27a5233dcdcc341a5df1ebbe Mon Sep 17 00:00:00 2001 From: vlkrs Date: Sat, 11 Jul 2026 22:51:56 +0200 Subject: [PATCH 072/215] link: Find versioned shared libraries on OpenBSD See https://github.com/ziglang/zig/pull/18475 for a prior attempt at implementing this --- src/link.zig | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/link.zig b/src/link.zig index 15d9fcb513a8b329d6ebfbc6cf66d92b02352bc8..8278be5eac7af60512123b66cb6883ae3fa3cf24 100644 --- a/src/link.zig +++ b/src/link.zig @@ -2239,6 +2239,63 @@ fn resolveLibInput( return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); } + // In the case of OpenBSD, dynamic libraries are always versioned, without + // unversioned symlinks, so we need to look for the highest-versioned shared + // library. + if (target.isOpenBSDLibC() and link_mode == .dynamic) versioned: { + const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name}); + + var dir = lib_directory.handle.openDir(io, ".", .{ .iterate = true }) catch |err| switch (err) { + error.NotDir, error.FileNotFound => break :versioned, + else => |e| fatal("unable to search for shared library '{s}.*': {s}", .{ prefix, @errorName(e) }), + }; + defer dir.close(io); + + var best_match_version = std.SemanticVersion{ + .major = 0, + .minor = 0, + .patch = 0, + }; + var best_match: ?[]const u8 = null; + + var iter = dir.iterate(); + while (iter.next(io) catch |err| { + fatal("unable to scan library directory '{s}'", .{@errorName(err)}); + }) |entry| { + if (entry.kind != .file) continue; + if (!std.mem.startsWith(u8, entry.name, prefix)) continue; + + const rest = entry.name[prefix.len..]; + var sit = std.mem.splitScalar(u8, rest, '.'); + const major_str = sit.next() orelse continue; + const minor_str = sit.next() orelse continue; + if (sit.next() != null) continue; + const major = std.fmt.parseInt(usize, major_str, 10) catch continue; + const minor = std.fmt.parseInt(usize, minor_str, 10) catch continue; + + if (major > best_match_version.major or (major == best_match_version.major and minor >= best_match_version.minor)) { + best_match_version.major = major; + best_match_version.minor = minor; + best_match = try arena.dupe(u8, entry.name); + } + } + + if (best_match) |found| { + const test_path: Path = .{ + .root_dir = lib_directory, + .sub_path = found, + }; + try checked_paths.print(gpa, "\n {f}", .{test_path}); + switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, .{ + .path = test_path, + .query = name_query.query, + }, link_mode, color)) { + .no_match => {}, + .ok => return .ok, + } + } + } + return .no_match; } -- 2.54.0 From d3f6408a418e459a0b0f77d63e05e311c4ea71e8 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 30 Jul 2026 17:48:35 +0200 Subject: [PATCH 073/215] link: simplify OpenBSD versioned shlib search And add a bit more detail about the intent in the comment. --- src/link.zig | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/link.zig b/src/link.zig index 8278be5eac7af60512123b66cb6883ae3fa3cf24..58534f63f8b6e2e2840201eebbe4fd69af07ac33 100644 --- a/src/link.zig +++ b/src/link.zig @@ -2240,8 +2240,8 @@ fn resolveLibInput( } // In the case of OpenBSD, dynamic libraries are always versioned, without - // unversioned symlinks, so we need to look for the highest-versioned shared - // library. + // unversioned symlinks. OpenBSD patches LLD to select the highest-versioned + // shared library, and this code is intended to match that upstream behavior. if (target.isOpenBSDLibC() and link_mode == .dynamic) versioned: { const prefix = try std.fmt.allocPrint(arena, "lib{s}.so.", .{lib_name}); @@ -2251,11 +2251,8 @@ fn resolveLibInput( }; defer dir.close(io); - var best_match_version = std.SemanticVersion{ - .major = 0, - .minor = 0, - .patch = 0, - }; + var best_match_major: u32 = 0; + var best_match_minor: u32 = 0; var best_match: ?[]const u8 = null; var iter = dir.iterate(); @@ -2270,12 +2267,12 @@ fn resolveLibInput( const major_str = sit.next() orelse continue; const minor_str = sit.next() orelse continue; if (sit.next() != null) continue; - const major = std.fmt.parseInt(usize, major_str, 10) catch continue; - const minor = std.fmt.parseInt(usize, minor_str, 10) catch continue; + const major = std.fmt.parseInt(u32, major_str, 10) catch continue; + const minor = std.fmt.parseInt(u32, minor_str, 10) catch continue; - if (major > best_match_version.major or (major == best_match_version.major and minor >= best_match_version.minor)) { - best_match_version.major = major; - best_match_version.minor = minor; + if (major > best_match_major or (major == best_match_major and minor >= best_match_minor)) { + best_match_major = major; + best_match_minor = minor; best_match = try arena.dupe(u8, entry.name); } } -- 2.54.0 From b6361fa84a5c8f217af5771e345387752fd5c581 Mon Sep 17 00:00:00 2001 From: Ennui Langeweile Date: Tue, 28 Jul 2026 22:51:49 -0300 Subject: [PATCH 074/215] Enable `extended-const` extension in stage1 Considering Debian 12 has Binaryen 108, we can now remove the explicit exclusion of `extended-const` (v107). --- build.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 0bd1abe03359bdd5c84086c95286568022a53bc4..74ef42a775985c90dd8a5b6b80a0926e4bc6012b 100644 --- a/build.zig +++ b/build.zig @@ -763,9 +763,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { .optimize = .ReleaseSmall, .target = b.resolveTargetQuery(std.Target.Query.parse(.{ .arch_os_abi = "wasm32-wasi", - // * `extended_const` is not supported by the `wasm-opt` version in CI. // * `nontrapping_bulk_memory_len0` is supported by `wasm2c`. - .cpu_features = "baseline-extended_const+nontrapping_bulk_memory_len0", + .cpu_features = "baseline+nontrapping_bulk_memory_len0", }) catch unreachable), }); @@ -809,6 +808,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { "-Oz", "--enable-bulk-memory", "--enable-mutable-globals", + "--enable-extended-const", "--enable-nontrapping-float-to-int", "--enable-sign-ext", }); -- 2.54.0 From d632f2a5b43e2e7adba1b742d16ce15d74a0accb Mon Sep 17 00:00:00 2001 From: Ennui Langeweile Date: Tue, 28 Jul 2026 23:22:15 -0300 Subject: [PATCH 075/215] Use single-space indentation for wasm2c's generated code This pretty much halves the file size of the generated C source code. I have decided to not touch the initial code since I don't believe it would be that beneficial. --- stage1/FuncGen.h | 6 +++--- stage1/wasm2c.c | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/stage1/FuncGen.h b/stage1/FuncGen.h index 494dd202b224fdb927efc3119f670fafa1def207..5f62b249862ac29656d7d1231d55504b93746fd4 100644 --- a/stage1/FuncGen.h +++ b/stage1/FuncGen.h @@ -52,17 +52,17 @@ static void FuncGen_free(struct FuncGen *self) { } static void FuncGen_outdent(struct FuncGen *self, FILE *out) { - for (uint32_t i = 0; i < self->block_i; i += 1) fputs(" ", out); + for (uint32_t i = 0; i < self->block_i; i += 1) fputs(" ", out); } static void FuncGen_indent(struct FuncGen *self, FILE *out) { FuncGen_outdent(self, out); - fputs(" ", out); + fputs(" ", out); } static void FuncGen_cont(struct FuncGen *self, FILE *out) { FuncGen_indent(self, out); - fputs(" ", out); + fputs(" ", out); } static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) { diff --git a/stage1/wasm2c.c b/stage1/wasm2c.c index adbf8667e5fbc8d6a4a0c56c26d78ea2185543bb..8363a332b4063ae37bafa10f53832aea91e56c03 100644 --- a/stage1/wasm2c.c +++ b/stage1/wasm2c.c @@ -518,8 +518,8 @@ int main(int argc, char **argv) { } fprintf(out, ") {\n" - " init();\n" - " %sf%" PRIu32 "(", + " init();\n" + " %sf%" PRIu32 "(", func_type->result->len > 0 ? "return " : "", idx - imports_len); for (uint32_t param_i = 0; param_i < func_type->param->len; param_i += 1) { if (param_i > 0) fputs(", ", out); @@ -552,7 +552,7 @@ int main(int argc, char **argv) { uint32_t segment_len = InputStream_readLeb128_u32(&in); for (uint32_t i = 0; i < segment_len; i += 1) { uint32_t func_id = InputStream_readLeb128_u32(&in); - fprintf(out, " t%" PRIu32 "[UINT32_C(%" PRIu32 ")] = (void (*)(void))&", + fprintf(out, " t%" PRIu32 "[UINT32_C(%" PRIu32 ")] = (void (*)(void))&", table_idx, offset + i); if (func_id < imports_len) fprintf(out, "%s_%s", imports[func_id].mod, imports[func_id].name); @@ -2260,9 +2260,9 @@ int main(int argc, char **argv) { uint32_t len = InputStream_readLeb128_u32(&in); fputs("static void init_data(void) {\n", out); for (uint32_t i = 0; i < mems_len; i += 1) - fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n" - " c%" PRIu32 " = p%" PRIu32 ";\n" - " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n", + fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n" + " c%" PRIu32 " = p%" PRIu32 ";\n" + " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n", i, mems[i].limits.min, i, i, i, i); for (uint32_t segment_i = 0; segment_i < len; segment_i += 1) { uint32_t mem_idx; @@ -2280,15 +2280,15 @@ int main(int argc, char **argv) { uint32_t offset = evalExpr(&in); uint32_t segment_len = InputStream_readLeb128_u32(&in); fputc('\n', out); - fprintf(out, " static const uint8_t s%" PRIu32 "[UINT32_C(%" PRIu32 ")] = {", + fprintf(out, " static const uint8_t s%" PRIu32 "[UINT32_C(%" PRIu32 ")] = {", segment_i, segment_len); for (uint32_t i = 0; i < segment_len; i += 1) { if (i % 32 == 0) fputs("\n ", out); fprintf(out, " 0x%02hhX,", InputStream_readByte(&in)); } fprintf(out, "\n" - " };\n" - " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n", + " };\n" + " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n", mem_idx, offset, segment_i, segment_len); } fputs("}\n", out); -- 2.54.0 From ea006188aaf110a33cbf0ca00888306f263cce98 Mon Sep 17 00:00:00 2001 From: David Senoner Date: Wed, 29 Jul 2026 14:08:23 +0200 Subject: [PATCH 076/215] elf: remove all deprecated usages and definitions of std.elf.PT_* --- lib/compiler/objcopy.zig | 2 +- lib/std/Build/Step/Compile.zig | 2 +- lib/std/dynamic_library.zig | 8 ++-- lib/std/elf.zig | 41 -------------------- lib/std/os/linux/tls.zig | 8 ++-- lib/std/os/linux/vdso.zig | 4 +- lib/std/pie.zig | 2 +- lib/std/posix/test.zig | 2 +- lib/std/start.zig | 4 +- lib/std/zig/system.zig | 8 ++-- src/link/Elf.zig | 70 +++++++++++++++++----------------- src/link/Lld.zig | 4 +- 12 files changed, 57 insertions(+), 98 deletions(-) diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 857299a60e16f410c3eb54ca6be8382c33b99567..136b48ef4c0cbadfd6f9309bfda8660fedb613d0 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -435,7 +435,7 @@ const BinaryElfOutput = struct { var program_headers = elf_hdr.iterateProgramHeaders(in); while (try program_headers.next()) |phdr| { - if (phdr.p_type == elf.PT_LOAD) { + if (phdr.p_type == @backingInt(elf.PT.LOAD)) { const newSegment = try allocator.create(BinaryElfSegment); newSegment.physicalAddress = phdr.p_paddr; diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index b14e0c254846d0bda46e06f735015f877dcf9a36..90d88f3a20785f3cb892b080212b8cda9afd5f88 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -101,7 +101,7 @@ each_lib_rpath: ?bool = null, /// This option overrides the CLI argument passed to `zig build`. build_id: ?std.zig.BuildId = null, -/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF +/// Create a .eh_frame_hdr section and a PT.GNU_EH_FRAME segment in the ELF /// file. link_eh_frame_hdr: bool = false, link_emit_relocs: bool = false, diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 0161644439803e7fc6dd4fbb1c1610235d97b5e0..767821f9ffe6743e1a5579ea6e231c22e5635124 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -103,7 +103,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn { pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator { const _DYNAMIC = get_DYNAMIC() orelse { - // No PT_DYNAMIC means this is a statically-linked non-PIE program. + // No PT.DYNAMIC means this is a statically-linked non-PIE program. return .{ .current = null }; }; @@ -263,8 +263,8 @@ pub const ElfDynLib = struct { }) { const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); switch (ph.p_type) { - elf.PT_LOAD => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz), - elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)), + @backingInt(elf.PT.LOAD) => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz), + @backingInt(elf.PT.DYNAMIC) => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)), else => {}, } } @@ -294,7 +294,7 @@ pub const ElfDynLib = struct { }) { const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); switch (ph.p_type) { - elf.PT_LOAD => { + @backingInt(elf.PT.LOAD) => { // The VirtAddr may not be page-aligned; in such case there will be // extra nonsense mapped before/after the VirtAddr,MemSiz const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, page_size) - 1); diff --git a/lib/std/elf.zig b/lib/std/elf.zig index e96cb50f97512239ff86e648d4dabd91eb5f01e4..d731f44289673ae800438ac34310400ed690ec85 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -290,47 +290,6 @@ pub const VER_FLG_BASE = 1; /// Weak version identifier pub const VER_FLG_WEAK = 2; -/// Deprecated, use `@intFromEnum(std.elf.PT.NULL)` -pub const PT_NULL = @backingInt(std.elf.PT.NULL); -/// Deprecated, use `@intFromEnum(std.elf.PT.LOAD)` -pub const PT_LOAD = @backingInt(std.elf.PT.LOAD); -/// Deprecated, use `@intFromEnum(std.elf.PT.DYNAMIC)` -pub const PT_DYNAMIC = @backingInt(std.elf.PT.DYNAMIC); -/// Deprecated, use `@intFromEnum(std.elf.PT.INTERP)` -pub const PT_INTERP = @backingInt(std.elf.PT.INTERP); -/// Deprecated, use `@intFromEnum(std.elf.PT.NOTE)` -pub const PT_NOTE = @backingInt(std.elf.PT.NOTE); -/// Deprecated, use `@intFromEnum(std.elf.PT.SHLIB)` -pub const PT_SHLIB = @backingInt(std.elf.PT.SHLIB); -/// Deprecated, use `@intFromEnum(std.elf.PT.PHDR)` -pub const PT_PHDR = @backingInt(std.elf.PT.PHDR); -/// Deprecated, use `@intFromEnum(std.elf.PT.TLS)` -pub const PT_TLS = @backingInt(std.elf.PT.TLS); -/// Deprecated, use `std.elf.PT.NUM`. -pub const PT_NUM = PT.NUM; -/// Deprecated, use `@intFromEnum(std.elf.PT.LOOS)` -pub const PT_LOOS = @backingInt(std.elf.PT.LOOS); -/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_EH_FRAME)` -pub const PT_GNU_EH_FRAME = @backingInt(std.elf.PT.GNU_EH_FRAME); -/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_STACK)` -pub const PT_GNU_STACK = @backingInt(std.elf.PT.GNU_STACK); -/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_RELRO)` -pub const PT_GNU_RELRO = @backingInt(std.elf.PT.GNU_RELRO); -/// Deprecated, use `@intFromEnum(std.elf.PT.LOSUNW)` -pub const PT_LOSUNW = @backingInt(std.elf.PT.LOSUNW); -/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWBSS)` -pub const PT_SUNWBSS = @backingInt(std.elf.PT.SUNWBSS); -/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWSTACK)` -pub const PT_SUNWSTACK = @backingInt(std.elf.PT.SUNWSTACK); -/// Deprecated, use `@intFromEnum(std.elf.PT.HISUNW)` -pub const PT_HISUNW = @backingInt(std.elf.PT.HISUNW); -/// Deprecated, use `@intFromEnum(std.elf.PT.HIOS)` -pub const PT_HIOS = @backingInt(std.elf.PT.HIOS); -/// Deprecated, use `@intFromEnum(std.elf.PT.LOPROC)` -pub const PT_LOPROC = @backingInt(std.elf.PT.LOPROC); -/// Deprecated, use `@intFromEnum(std.elf.PT.HIPROC)` -pub const PT_HIPROC = @backingInt(std.elf.PT.HIPROC); - pub const PN_XNUM = 0xffff; /// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)` diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index e02ba39840497e2dec5d55ed1a7bb4a05b17ad01..79664061b1de96bbc00cf0714e4d8a82a5aa5f88 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -22,7 +22,7 @@ const page_size_min = std.heap.page_size_min; /// Represents an ELF TLS variant. /// /// In all variants, the TP and the TLS blocks must be aligned to the `p_align` value in the -/// `PT_TLS` ELF program header. Everything else has natural alignment. +/// `PT.TLS` ELF program header. Everything else has natural alignment. /// /// The location of the DTV does not actually matter. For simplicity, we put it in the TLS area, but /// there is no actual ABI requirement that it reside there. @@ -489,8 +489,8 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void { for (phdrs) |*phdr| { switch (phdr.p_type) { - elf.PT_PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr, - elf.PT_TLS => tls_phdr = phdr, + @backingInt(elf.PT.PHDR) => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr, + @backingInt(elf.PT.TLS) => tls_phdr = phdr, else => {}, } } @@ -503,7 +503,7 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void { align_factor = phdr.p_align; // The effective size in memory is represented by `p_memsz`; the length of the data stored - // in the `PT_TLS` segment is `p_filesz` and may be less than the former. + // in the `PT.TLS` segment is `p_filesz` and may be less than the former. block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz]; block_size = phdr.p_memsz; } else { diff --git a/lib/std/os/linux/vdso.zig b/lib/std/os/linux/vdso.zig index 1106ee8bf173dd6eaff0fe372e490249d91dd89f..cc058b7ffcc3ab64f0fc7beaf0afa233d3514483 100644 --- a/lib/std/os/linux/vdso.zig +++ b/lib/std/os/linux/vdso.zig @@ -25,8 +25,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize { // of the memory space (e.g. p_vaddr = 0xffffffffff700000 on WSL1). // Wrapping operations are used on this line as well as subsequent calculations relative to base // (lines 47, 78) to ensure no overflow check is tripped. - elf.PT_LOAD => base = vdso_addr +% this_ph.p_offset -% this_ph.p_vaddr, - elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)), + @backingInt(elf.PT.LOAD) => base = vdso_addr +% this_ph.p_offset -% this_ph.p_vaddr, + @backingInt(elf.PT.DYNAMIC) => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)), else => {}, } } diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 0252cde9e8f0161ae5a3767723c3853f94ec82f0..498fe3672e1c6e10fa940f40f2dcc380b2c49f63 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -303,7 +303,7 @@ pub fn relocate(phdrs: []const elf.Phdr) void { // the theoretical load addresses for the `_DYNAMIC` symbol. const base_addr = base: { for (phdrs) |*phdr| { - if (phdr.p_type != elf.PT_DYNAMIC) continue; + if (phdr.p_type != @backingInt(elf.PT.DYNAMIC)) continue; break :base @intFromPtr(dynv) - phdr.p_vaddr; } // This is not supposed to happen for well-formed binaries. diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index 8accb90cb7f9c79b3246fb974c838c9c28e7245d..4fb68855b5a5953b709fae4f893bc051a50dbf09 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -75,7 +75,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { // Count how many libraries are loaded counter.* += @as(usize, 1); - // The image should contain at least a PT_LOAD segment + // The image should contain at least a PT.LOAD segment if (info.phnum < 1) return error.MissingPtLoadSegment; // Quick & dirty validation of the phdr pointers, make sure we're not diff --git a/lib/std/start.zig b/lib/std/start.zig index 2530b80d360c4e9b61bb8f2d4e25006d20aea2c3..cd72a52847d60eaa5dd30bd0a161ddff99bfc3f0 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -621,7 +621,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { std.os.linux.tls.initStatic(phdrs); } - // The way Linux executables represent stack size is via the PT_GNU_STACK + // The way Linux executables represent stack size is via the PT.GNU_STACK // program header. However the kernel does not recognize it; it always gives 8 MiB. // Here we look for the stack size in our program headers and use setrlimit // to ask for more stack space. @@ -649,7 +649,7 @@ fn expandStackSize(phdrs: []elf.Phdr) void { @disableInstrumentation(); for (phdrs) |*phdr| { switch (phdr.p_type) { - elf.PT_GNU_STACK => { + @backingInt(elf.PT.GNU_STACK) => { if (phdr.p_memsz == 0) break; assert(phdr.p_memsz % std.heap.page_size_min == 0); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 060fd1d97643beac4e5724a12ea26427e7500a31..083e7bb90f0ffb5acabf3470414262834e3cb0b1 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -597,14 +597,14 @@ fn abiAndDynamicLinkerFromFile( .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), .dynamic_linker = query.dynamic_linker orelse .none, }; - var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC + var rpath_offset: ?u64 = null; // Found inside PT.DYNAMIC const look_for_ld = query.dynamic_linker == null; var got_dyn_section: bool = false; { var it = header.iterateProgramHeaders(file_reader); while (try it.next()) |phdr| switch (phdr.p_type) { - elf.PT_INTERP => { + @backingInt(elf.PT.INTERP) => { got_dyn_section = true; if (look_for_ld) { @@ -613,7 +613,7 @@ fn abiAndDynamicLinkerFromFile( const filesz: usize = @intCast(p_filesz); try file_reader.seekTo(phdr.p_offset); try file_reader.interface.readSliceAll(result.dynamic_linker.buffer[0..filesz]); - // PT_INTERP includes a null byte in filesz. + // PT.INTERP includes a null byte in filesz. const len = filesz - 1; // dynamic_linker.max_byte is "max", not "len". // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. @@ -631,7 +631,7 @@ fn abiAndDynamicLinkerFromFile( } }, // We only need this for detecting glibc version. - elf.PT_DYNAMIC => { + @backingInt(elf.PT.DYNAMIC) => { got_dyn_section = true; if (builtin.target.os.tag == .linux and result.isGnuLibC() and query.glibc_version == null) { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index cda6d5321069bfe23b53efb10eb6dc6da8a0bc6d..de53f98bd5d3a83bd548d4c8b7d41b57a60d2cba 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -159,21 +159,21 @@ const ProgramHeaderIndex = enum(u16) { }; const ProgramHeaderIndexes = struct { - /// PT_PHDR + /// PT.PHDR table: OptionalProgramHeaderIndex = .none, - /// PT_LOAD for PHDR table + /// PT.LOAD for PHDR table /// We add this special load segment to ensure the EHDR and PHDR table are always /// loaded into memory. table_load: OptionalProgramHeaderIndex = .none, - /// PT_INTERP + /// PT.INTERP interp: OptionalProgramHeaderIndex = .none, - /// PT_DYNAMIC + /// PT.DYNAMIC dynamic: OptionalProgramHeaderIndex = .none, - /// PT_GNU_EH_FRAME + /// PT.GNU_EH_FRAME gnu_eh_frame: OptionalProgramHeaderIndex = .none, - /// PT_GNU_STACK + /// PT.GNU_STACK gnu_stack: OptionalProgramHeaderIndex = .none, - /// PT_TLS + /// PT.TLS /// TODO I think ELF permits multiple TLS segments but for now, assume one per file. tls: OptionalProgramHeaderIndex = .none, }; @@ -334,7 +334,7 @@ pub fn createEmpty( if (!is_obj_or_ar) { try self.dynstrtab.append(gpa, 0); - // Initialize PT_PHDR program header + // Initialize PT.PHDR program header const p_align: u16 = switch (self.ptr_width) { .p32 => @alignOf(elf.Elf32_Phdr), .p64 => @alignOf(elf.Elf64_Phdr), @@ -350,7 +350,7 @@ pub fn createEmpty( const max_nphdrs = comptime getMaxNumberOfPhdrs(); const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size); self.phdr_indexes.table = (try self.addPhdr(.{ - .type = elf.PT_PHDR, + .type = @backingInt(elf.PT.PHDR), .flags = elf.PF_R, .@"align" = p_align, .addr = self.image_base + ehsize, @@ -359,7 +359,7 @@ pub fn createEmpty( .memsz = reserved, })).toOptional(); self.phdr_indexes.table_load = (try self.addPhdr(.{ - .type = elf.PT_LOAD, + .type = @backingInt(elf.PT.LOAD), .flags = elf.PF_R, .@"align" = self.page_size, .addr = self.image_base, @@ -514,7 +514,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { } for (self.phdrs.items) |phdr| { - if (phdr.p_type != elf.PT_LOAD) continue; + if (phdr.p_type != @backingInt(elf.PT.LOAD)) continue; const increased_size = padToIdeal(phdr.p_filesz); const test_end = phdr.p_offset +| increased_size; if (start < test_end) { @@ -2091,26 +2091,26 @@ fn initSpecialPhdrs(self: *Elf) !void { if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) { self.phdr_indexes.interp = (try self.addPhdr(.{ - .type = elf.PT_INTERP, + .type = @backingInt(elf.PT.INTERP), .flags = elf.PF_R, .@"align" = 1, })).toOptional(); } if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) { self.phdr_indexes.dynamic = (try self.addPhdr(.{ - .type = elf.PT_DYNAMIC, + .type = @backingInt(elf.PT.DYNAMIC), .flags = elf.PF_R | elf.PF_W, })).toOptional(); } if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) { self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{ - .type = elf.PT_GNU_EH_FRAME, + .type = @backingInt(elf.PT.GNU_EH_FRAME), .flags = elf.PF_R, })).toOptional(); } if (self.phdr_indexes.gnu_stack == .none) { self.phdr_indexes.gnu_stack = (try self.addPhdr(.{ - .type = elf.PT_GNU_STACK, + .type = @backingInt(elf.PT.GNU_STACK), .flags = elf.PF_W | elf.PF_R, .memsz = self.base.stack_size, .@"align" = 1, @@ -2122,7 +2122,7 @@ fn initSpecialPhdrs(self: *Elf) !void { } else false; if (has_tls and self.phdr_indexes.tls == .none) { self.phdr_indexes.tls = (try self.addPhdr(.{ - .type = elf.PT_TLS, + .type = @backingInt(elf.PT.TLS), .flags = elf.PF_R, .@"align" = 1, })).toOptional(); @@ -2262,13 +2262,13 @@ fn setHashSections(self: *Elf) !void { fn phdrRank(phdr: elf.Elf64_Phdr) u8 { return switch (phdr.p_type) { - elf.PT_NULL => 0, - elf.PT_PHDR => 1, - elf.PT_INTERP => 2, - elf.PT_LOAD => 3, - elf.PT_DYNAMIC, elf.PT_TLS => 4, - elf.PT_GNU_EH_FRAME => 5, - elf.PT_GNU_STACK => 6, + @backingInt(elf.PT.NULL) => 0, + @backingInt(elf.PT.PHDR) => 1, + @backingInt(elf.PT.INTERP) => 2, + @backingInt(elf.PT.LOAD) => 3, + @backingInt(elf.PT.DYNAMIC), @backingInt(elf.PT.TLS) => 4, + @backingInt(elf.PT.GNU_EH_FRAME) => 5, + @backingInt(elf.PT.GNU_STACK) => 6, else => 7, }; } @@ -2655,8 +2655,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { if (shdr.sh_type == elf.SHT_NULL) continue; if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; const flags = shdrToPhdrFlags(shdr.sh_flags); - if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) { - _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD }); + if (self.getPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }) == .none) { + _ = try self.addPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }); } } } @@ -2817,7 +2817,7 @@ pub fn allocateAllocSections(self: *Elf) !void { } const first = slice.items(.shdr)[cover.items[0]]; - const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?; + const phndx = self.getPhdr(.{ .type = @backingInt(elf.PT.LOAD), .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?; const phdr = &self.phdrs.items[phndx.int()]; const allocated_size = self.allocatedSize(phdr.p_offset); if (filesz > allocated_size) { @@ -3906,15 +3906,15 @@ fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void if (write) flags[1] = 'W'; if (read) flags[2] = 'R'; const p_type = switch (phdr.p_type) { - elf.PT_LOAD => "LOAD", - elf.PT_TLS => "TLS", - elf.PT_GNU_EH_FRAME => "GNU_EH_FRAME", - elf.PT_GNU_STACK => "GNU_STACK", - elf.PT_DYNAMIC => "DYNAMIC", - elf.PT_INTERP => "INTERP", - elf.PT_NULL => "NULL", - elf.PT_PHDR => "PHDR", - elf.PT_NOTE => "NOTE", + @backingInt(elf.PT.LOAD) => "LOAD", + @backingInt(elf.PT.TLS) => "TLS", + @backingInt(elf.PT.GNU_EH_FRAME) => "GNU_EH_FRAME", + @backingInt(elf.PT.GNU_STACK) => "GNU_STACK", + @backingInt(elf.PT.DYNAMIC) => "DYNAMIC", + @backingInt(elf.PT.INTERP) => "INTERP", + @backingInt(elf.PT.NULL) => "NULL", + @backingInt(elf.PT.PHDR) => "PHDR", + @backingInt(elf.PT.NOTE) => "NOTE", else => "UNKNOWN", }; try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{ diff --git a/src/link/Lld.zig b/src/link/Lld.zig index cf64d3fd5bc51817cc86a7554ac65ee7aa53e373..62b92f00e56db89b856acf5927f670273dcc2b92 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -1021,8 +1021,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { } 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 + // 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"); -- 2.54.0 From 8d888624567d6c5170ddbeda5f312c3b1762261b Mon Sep 17 00:00:00 2001 From: David Senoner Date: Thu, 30 Jul 2026 18:03:19 +0200 Subject: [PATCH 077/215] elf: remove usages of deprecated elf.Phdr --- lib/std/dynamic_library.zig | 32 ++++++++++++++++---------------- lib/std/os/emscripten.zig | 2 +- lib/std/os/linux/tls.zig | 22 +++++++++++----------- lib/std/os/linux/vdso.zig | 10 +++++----- lib/std/pie.zig | 6 +++--- lib/std/start.zig | 16 ++++++++-------- 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 767821f9ffe6743e1a5579ea6e231c22e5635124..98bcafb88b16504cfab619d8407675b5014fd6e9 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -261,10 +261,10 @@ pub const ElfDynLib = struct { i += 1; ph_addr += eh.e_phentsize; }) { - const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); - switch (ph.p_type) { - @backingInt(elf.PT.LOAD) => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz), - @backingInt(elf.PT.DYNAMIC) => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)), + const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); + switch (ph.type) { + .LOAD => virt_addr_end = @max(virt_addr_end, ph.vaddr + ph.memsz), + .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.offset)), else => {}, } } @@ -292,23 +292,23 @@ pub const ElfDynLib = struct { i += 1; ph_addr += eh.e_phentsize; }) { - const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); - switch (ph.p_type) { - @backingInt(elf.PT.LOAD) => { + const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); + switch (ph.type) { + .LOAD => { // The VirtAddr may not be page-aligned; in such case there will be // extra nonsense mapped before/after the VirtAddr,MemSiz - const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, page_size) - 1); - const extra_bytes = (base + ph.p_vaddr) - aligned_addr; - const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size); + const aligned_addr = (base + ph.vaddr) & ~(@as(usize, page_size) - 1); + const extra_bytes = (base + ph.vaddr) - aligned_addr; + const extended_memsz = mem.alignForward(usize, ph.memsz + extra_bytes, page_size); const ptr = @as([*]align(std.heap.page_size_min) u8, @ptrFromInt(aligned_addr)); - const prot = elfToProt(ph.p_flags); + const prot = elfToProt(ph.flags); _ = try posix.mmap( ptr, extended_memsz, prot, .{ .TYPE = .PRIVATE, .FIXED = true }, file.handle, - ph.p_offset - extra_bytes, + ph.offset - extra_bytes, ); }, else => {}, @@ -517,11 +517,11 @@ pub const ElfDynLib = struct { return null; } - fn elfToProt(elf_prot: u64) posix.PROT { + fn elfToProt(elf_prot: elf.PF) posix.PROT { return .{ - .READ = (elf_prot & elf.PF_R) != 0, - .WRITE = (elf_prot & elf.PF_W) != 0, - .EXEC = (elf_prot & elf.PF_X) != 0, + .READ = elf_prot.R, + .WRITE = elf_prot.W, + .EXEC = elf_prot.X, }; } }; diff --git a/lib/std/os/emscripten.zig b/lib/std/os/emscripten.zig index 5df52dd9b87fada9ccc2d5286d864902b3894e3d..da0c85d1b05a5758a52aeae315446e91fc982477 100644 --- a/lib/std/os/emscripten.zig +++ b/lib/std/os/emscripten.zig @@ -730,7 +730,7 @@ pub const clock_t = i32; pub const dl_phdr_info = extern struct { addr: usize, name: ?[*:0]const u8, - phdr: [*]std.elf.Phdr, + phdr: [*]std.elf.ElfN.Phdr, phnum: u16, }; diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 79664061b1de96bbc00cf0714e4d8a82a5aa5f88..a42c44f29fe48de3383752055d7a63947ec52fd2 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -480,17 +480,17 @@ pub fn getThreadPointer() usize { }; } -fn computeAreaDesc(phdrs: []elf.Phdr) void { +fn computeAreaDesc(phdrs: []elf.ElfN.Phdr) void { @setRuntimeSafety(false); @disableInstrumentation(); - var tls_phdr: ?*elf.Phdr = null; + var tls_phdr: ?*elf.ElfN.Phdr = null; var img_base: usize = 0; for (phdrs) |*phdr| { - switch (phdr.p_type) { - @backingInt(elf.PT.PHDR) => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr, - @backingInt(elf.PT.TLS) => tls_phdr = phdr, + switch (phdr.type) { + .PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.vaddr, + .TLS => tls_phdr = phdr, else => {}, } } @@ -500,12 +500,12 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void { var block_size: usize = undefined; if (tls_phdr) |phdr| { - align_factor = phdr.p_align; + align_factor = phdr.@"align"; - // The effective size in memory is represented by `p_memsz`; the length of the data stored - // in the `PT.TLS` segment is `p_filesz` and may be less than the former. - block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz]; - block_size = phdr.p_memsz; + // The effective size in memory is represented by `memsz`; the length of the data stored + // in the `PT.TLS` segment is `filesz` and may be less than the former. + block_init = @as([*]u8, @ptrFromInt(img_base + phdr.vaddr))[0..phdr.filesz]; + block_size = phdr.memsz; } else { align_factor = @alignOf(usize); @@ -651,7 +651,7 @@ var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined; /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, /// and assigns the architecture-specific value to the TP register. -pub fn initStatic(phdrs: []elf.Phdr) void { +pub fn initStatic(phdrs: []elf.ElfN.Phdr) void { @setRuntimeSafety(false); @disableInstrumentation(); diff --git a/lib/std/os/linux/vdso.zig b/lib/std/os/linux/vdso.zig index cc058b7ffcc3ab64f0fc7beaf0afa233d3514483..53be1bf9d51f0048d57074313fa49aff65e0e6a2 100644 --- a/lib/std/os/linux/vdso.zig +++ b/lib/std/os/linux/vdso.zig @@ -19,14 +19,14 @@ pub fn lookup(vername: []const u8, name: []const u8) usize { i += 1; ph_addr += eh.e_phentsize; }) { - const this_ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); - switch (this_ph.p_type) { + const this_ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); + switch (this_ph.type) { // On WSL1 as well as older kernels, the VDSO ELF image is pre-linked in the upper half - // of the memory space (e.g. p_vaddr = 0xffffffffff700000 on WSL1). + // of the memory space (e.g. vaddr = 0xffffffffff700000 on WSL1). // Wrapping operations are used on this line as well as subsequent calculations relative to base // (lines 47, 78) to ensure no overflow check is tripped. - @backingInt(elf.PT.LOAD) => base = vdso_addr +% this_ph.p_offset -% this_ph.p_vaddr, - @backingInt(elf.PT.DYNAMIC) => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)), + .LOAD => base = vdso_addr +% this_ph.offset -% this_ph.vaddr, + .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.offset)), else => {}, } } diff --git a/lib/std/pie.zig b/lib/std/pie.zig index 498fe3672e1c6e10fa940f40f2dcc380b2c49f63..bcec6acd590f391c56202ff897b364ee0d456554 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -293,7 +293,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { }; } -pub fn relocate(phdrs: []const elf.Phdr) void { +pub fn relocate(phdrs: []const elf.ElfN.Phdr) void { @setRuntimeSafety(false); @disableInstrumentation(); @@ -303,8 +303,8 @@ pub fn relocate(phdrs: []const elf.Phdr) void { // the theoretical load addresses for the `_DYNAMIC` symbol. const base_addr = base: { for (phdrs) |*phdr| { - if (phdr.p_type != @backingInt(elf.PT.DYNAMIC)) continue; - break :base @intFromPtr(dynv) - phdr.p_vaddr; + if (phdr.type != .DYNAMIC) continue; + break :base @intFromPtr(dynv) - phdr.vaddr; } // This is not supposed to happen for well-formed binaries. @trap(); diff --git a/lib/std/start.zig b/lib/std/start.zig index cd72a52847d60eaa5dd30bd0a161ddff99bfc3f0..6021da10325aa38a6be00d59ecc1d58634deba77 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -589,7 +589,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { else => continue, } } - break :init @as([*]elf.Phdr, @ptrFromInt(at_phdr))[0..at_phnum]; + break :init @as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr))[0..at_phnum]; }; // Apply the initial relocations as early as possible in the startup process. We cannot @@ -645,19 +645,19 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { std.process.exit(callMainWithArgs(argc, argv, envp)); } -fn expandStackSize(phdrs: []elf.Phdr) void { +fn expandStackSize(phdrs: []elf.ElfN.Phdr) void { @disableInstrumentation(); for (phdrs) |*phdr| { - switch (phdr.p_type) { - @backingInt(elf.PT.GNU_STACK) => { - if (phdr.p_memsz == 0) break; - assert(phdr.p_memsz % std.heap.page_size_min == 0); + switch (phdr.type) { + .GNU_STACK => { + if (phdr.memsz == 0) break; + assert(phdr.memsz % std.heap.page_size_min == 0); // Silently fail if we are unable to get limits. const limits = std.posix.getrlimit(.STACK) catch break; // Clamp to limits.max . - const wanted_stack_size = @min(phdr.p_memsz, limits.max); + const wanted_stack_size = @min(phdr.memsz, limits.max); if (wanted_stack_size > limits.cur) { std.posix.setrlimit(.STACK, .{ @@ -702,7 +702,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal .linux => { const at_phdr = std.c.getauxval(elf.AT_PHDR); const at_phnum = std.c.getauxval(elf.AT_PHNUM); - const phdrs = (@as([*]elf.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum]; + const phdrs = (@as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum]; expandStackSize(phdrs); }, .windows => { -- 2.54.0 From 4843120b4c3d3bb8cc8cb56b0185af24676616ff Mon Sep 17 00:00:00 2001 From: David Senoner Date: Wed, 29 Jul 2026 15:11:54 +0200 Subject: [PATCH 078/215] elf: remove usages of deprecated Elf32_Phdr --- lib/std/debug/SelfInfo/Elf.zig | 2 +- lib/std/elf.zig | 22 +++++++++++----------- src/link/Elf.zig | 30 +++++++++++++++--------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index eb60162dcb405709a7468e97ea4b755aaefe2d90..398a3f95a8933d489f67e3c9958084f2ed4e5660 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -518,7 +518,7 @@ const DlIterContext = struct { for (info.phdr[0..info.phnum]) |phdr| { if (phdr.type != .LOAD) continue; try context.si.ranges.append(gpa, .{ - // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000 + // Overflowing addition handles VSDOs having vaddr = 0xffffffffff700000 .start = info.addr +% phdr.vaddr, .len = phdr.memsz, .module_index = module_index, diff --git a/lib/std/elf.zig b/lib/std/elf.zig index d731f44289673ae800438ac34310400ed690ec85..97710d03c175cc48273b8e40c324bff122fc4caa 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -811,7 +811,7 @@ pub const ProgramHeaderIterator = struct { if (it.index >= it.phnum) return null; defer it.index += 1; - const size: u64 = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr); + const size: u64 = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32.Phdr); const offset = it.phoff + size * it.index; try it.file_reader.seekTo(offset); @@ -832,7 +832,7 @@ pub const ProgramHeaderBufferIterator = struct { if (it.index >= it.phnum) return null; defer it.index += 1; - const size: usize = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32_Phdr); + const size: usize = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32.Phdr); const offset = @as(usize, @intCast(it.phoff)) + size * it.index; var reader = Io.Reader.fixed(it.buf[offset..]); @@ -846,16 +846,16 @@ pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64 return phdr; } - const phdr = try reader.takeStruct(Elf32_Phdr, endian); + const phdr = try reader.takeStruct(Elf32.Phdr, endian); return .{ - .p_type = phdr.p_type, - .p_offset = phdr.p_offset, - .p_vaddr = phdr.p_vaddr, - .p_paddr = phdr.p_paddr, - .p_filesz = phdr.p_filesz, - .p_memsz = phdr.p_memsz, - .p_flags = phdr.p_flags, - .p_align = phdr.p_align, + .p_type = @backingInt(phdr.type), + .p_offset = phdr.offset, + .p_vaddr = phdr.vaddr, + .p_paddr = phdr.paddr, + .p_filesz = phdr.filesz, + .p_memsz = phdr.memsz, + .p_flags = @backingInt(phdr.flags), + .p_align = phdr.@"align", }; } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index de53f98bd5d3a83bd548d4c8b7d41b57a60d2cba..3f82771d536a6fcc6265b1b0b366943979d2faa7 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -336,7 +336,7 @@ pub fn createEmpty( // Initialize PT.PHDR program header const p_align: u16 = switch (self.ptr_width) { - .p32 => @alignOf(elf.Elf32_Phdr), + .p32 => @alignOf(elf.Elf32.Phdr), .p64 => @alignOf(elf.Elf64_Phdr), }; const ehsize: u64 = switch (self.ptr_width) { @@ -344,7 +344,7 @@ pub fn createEmpty( .p64 => @sizeOf(elf.Elf64_Ehdr), }; const phsize: u64 = switch (self.ptr_width) { - .p32 => @sizeOf(elf.Elf32_Phdr), + .p32 => @sizeOf(elf.Elf32.Phdr), .p64 => @sizeOf(elf.Elf64_Phdr), }; const max_nphdrs = comptime getMaxNumberOfPhdrs(); @@ -1477,13 +1477,13 @@ fn writePhdrTable(self: *Elf) !void { switch (self.ptr_width) { .p32 => { - const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len); + const buf = try gpa.alloc(elf.Elf32.Phdr, self.phdrs.items.len); defer gpa.free(buf); for (buf, 0..) |*phdr, i| { phdr.* = phdrTo32(self.phdrs.items[i]); if (foreign_endian) { - mem.byteSwapAllFields(elf.Elf32_Phdr, phdr); + mem.byteSwapAllFields(elf.Elf32.Phdr, phdr); } } try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset); @@ -1622,7 +1622,7 @@ pub fn writeElfHeader(self: *Elf) !void { index += 2; const e_phentsize: u16 = switch (self.ptr_width) { - .p32 => @sizeOf(elf.Elf32_Phdr), + .p32 => @sizeOf(elf.Elf32.Phdr), .p64 => @sizeOf(elf.Elf64_Phdr), }; mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian); @@ -2672,7 +2672,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { .p64 => @sizeOf(elf.Elf64_Ehdr), }; const phsize: u64 = switch (self.ptr_width) { - .p32 => @sizeOf(elf.Elf32_Phdr), + .p32 => @sizeOf(elf.Elf32.Phdr), .p64 => @sizeOf(elf.Elf64_Phdr), }; const needed_size = self.phdrs.items.len * phsize; @@ -3347,16 +3347,16 @@ pub fn archPtrWidthBytes(self: Elf) u8 { return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8)); } -fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { +fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32.Phdr { return .{ - .p_type = phdr.p_type, - .p_flags = phdr.p_flags, - .p_offset = @as(u32, @intCast(phdr.p_offset)), - .p_vaddr = @as(u32, @intCast(phdr.p_vaddr)), - .p_paddr = @as(u32, @intCast(phdr.p_paddr)), - .p_filesz = @as(u32, @intCast(phdr.p_filesz)), - .p_memsz = @as(u32, @intCast(phdr.p_memsz)), - .p_align = @as(u32, @intCast(phdr.p_align)), + .type = @fromBackingInt(phdr.p_type), + .flags = @fromBackingInt(phdr.p_flags), + .offset = @intCast(phdr.p_offset), + .vaddr = @intCast(phdr.p_vaddr), + .paddr = @intCast(phdr.p_paddr), + .filesz = @intCast(phdr.p_filesz), + .memsz = @intCast(phdr.p_memsz), + .@"align" = @intCast(phdr.p_align), }; } -- 2.54.0 From 574c80351da46a4ac836504c6591d5db068eaa06 Mon Sep 17 00:00:00 2001 From: David Senoner Date: Thu, 30 Jul 2026 18:38:51 +0200 Subject: [PATCH 079/215] elf: remove usages of deprecated Elf64_Phdr --- lib/compiler/objcopy.zig | 14 +-- lib/std/elf.zig | 28 +++--- lib/std/zig/system.zig | 12 +-- src/link/Elf.zig | 202 +++++++++++++++++++-------------------- 4 files changed, 128 insertions(+), 128 deletions(-) diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 136b48ef4c0cbadfd6f9309bfda8660fedb613d0..a54c61f5000ff569a7c34461e7db80b515d3d21d 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -435,13 +435,13 @@ const BinaryElfOutput = struct { var program_headers = elf_hdr.iterateProgramHeaders(in); while (try program_headers.next()) |phdr| { - if (phdr.p_type == @backingInt(elf.PT.LOAD)) { + if (phdr.type == .LOAD) { const newSegment = try allocator.create(BinaryElfSegment); - newSegment.physicalAddress = phdr.p_paddr; - newSegment.virtualAddress = phdr.p_vaddr; - newSegment.fileSize = @intCast(phdr.p_filesz); - newSegment.elfOffset = phdr.p_offset; + newSegment.physicalAddress = phdr.paddr; + newSegment.virtualAddress = phdr.vaddr; + newSegment.fileSize = @intCast(phdr.filesz); + newSegment.elfOffset = phdr.offset; newSegment.binaryOffset = 0; newSegment.firstSection = null; @@ -495,8 +495,8 @@ const BinaryElfOutput = struct { return self; } - fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64_Phdr) bool { - return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize); + fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64.Phdr) bool { + return segment.offset <= section.elfOffset and (segment.offset + segment.filesz) >= (section.elfOffset + section.fileSize); } fn sectionValidForOutput(shdr: anytype) bool { diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 97710d03c175cc48273b8e40c324bff122fc4caa..f2741734812a488ee400a82b7d7c4e159b61baaa 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -807,11 +807,11 @@ pub const ProgramHeaderIterator = struct { file_reader: *Io.File.Reader, index: usize = 0, - pub fn next(it: *ProgramHeaderIterator) !?Elf64_Phdr { + pub fn next(it: *ProgramHeaderIterator) !?Elf64.Phdr { if (it.index >= it.phnum) return null; defer it.index += 1; - const size: u64 = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32.Phdr); + const size: u64 = if (it.is_64) @sizeOf(Elf64.Phdr) else @sizeOf(Elf32.Phdr); const offset = it.phoff + size * it.index; try it.file_reader.seekTo(offset); @@ -828,11 +828,11 @@ pub const ProgramHeaderBufferIterator = struct { buf: []const u8, index: usize = 0, - pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64_Phdr { + pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64.Phdr { if (it.index >= it.phnum) return null; defer it.index += 1; - const size: usize = if (it.is_64) @sizeOf(Elf64_Phdr) else @sizeOf(Elf32.Phdr); + const size: usize = if (it.is_64) @sizeOf(Elf64.Phdr) else @sizeOf(Elf32.Phdr); const offset = @as(usize, @intCast(it.phoff)) + size * it.index; var reader = Io.Reader.fixed(it.buf[offset..]); @@ -840,22 +840,22 @@ pub const ProgramHeaderBufferIterator = struct { } }; -pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64_Phdr { +pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64.Phdr { if (is_64) { - const phdr = try reader.takeStruct(Elf64_Phdr, endian); + const phdr = try reader.takeStruct(Elf64.Phdr, endian); return phdr; } const phdr = try reader.takeStruct(Elf32.Phdr, endian); return .{ - .p_type = @backingInt(phdr.type), - .p_offset = phdr.offset, - .p_vaddr = phdr.vaddr, - .p_paddr = phdr.paddr, - .p_filesz = phdr.filesz, - .p_memsz = phdr.memsz, - .p_flags = @backingInt(phdr.flags), - .p_align = phdr.@"align", + .type = phdr.type, + .offset = phdr.offset, + .vaddr = phdr.vaddr, + .paddr = phdr.paddr, + .filesz = phdr.filesz, + .memsz = phdr.memsz, + .flags = phdr.flags, + .@"align" = phdr.@"align", }; } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 083e7bb90f0ffb5acabf3470414262834e3cb0b1..4d63d0c995024fa317bb59aca5e0fc2022c63c9b 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -603,15 +603,15 @@ fn abiAndDynamicLinkerFromFile( var got_dyn_section: bool = false; { var it = header.iterateProgramHeaders(file_reader); - while (try it.next()) |phdr| switch (phdr.p_type) { - @backingInt(elf.PT.INTERP) => { + while (try it.next()) |phdr| switch (phdr.type) { + .INTERP => { got_dyn_section = true; if (look_for_ld) { - const p_filesz = phdr.p_filesz; + const p_filesz = phdr.filesz; if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong; const filesz: usize = @intCast(p_filesz); - try file_reader.seekTo(phdr.p_offset); + try file_reader.seekTo(phdr.offset); try file_reader.interface.readSliceAll(result.dynamic_linker.buffer[0..filesz]); // PT.INTERP includes a null byte in filesz. const len = filesz - 1; @@ -631,11 +631,11 @@ fn abiAndDynamicLinkerFromFile( } }, // We only need this for detecting glibc version. - @backingInt(elf.PT.DYNAMIC) => { + .DYNAMIC => { got_dyn_section = true; if (builtin.target.os.tag == .linux and result.isGnuLibC() and query.glibc_version == null) { - var dyn_it = header.iterateDynamicSection(file_reader, phdr.p_offset, phdr.p_filesz); + var dyn_it = header.iterateDynamicSection(file_reader, phdr.offset, phdr.filesz); while (try dyn_it.next()) |dyn| { if (dyn.d_tag == elf.DT_RUNPATH) { rpath_offset = dyn.d_val; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3f82771d536a6fcc6265b1b0b366943979d2faa7..e22680a44a450739239051ad62d27067d2efe327 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -127,7 +127,7 @@ const SectionIndexes = struct { symtab: ?u32 = null, }; -const ProgramHeaderList = std.ArrayList(elf.Elf64_Phdr); +const ProgramHeaderList = std.ArrayList(elf.Elf64.Phdr); const OptionalProgramHeaderIndex = enum(u16) { none = std.math.maxInt(u16), @@ -337,7 +337,7 @@ pub fn createEmpty( // Initialize PT.PHDR program header const p_align: u16 = switch (self.ptr_width) { .p32 => @alignOf(elf.Elf32.Phdr), - .p64 => @alignOf(elf.Elf64_Phdr), + .p64 => @alignOf(elf.Elf64.Phdr), }; const ehsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Ehdr), @@ -345,7 +345,7 @@ pub fn createEmpty( }; const phsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32.Phdr), - .p64 => @sizeOf(elf.Elf64_Phdr), + .p64 => @sizeOf(elf.Elf64.Phdr), }; const max_nphdrs = comptime getMaxNumberOfPhdrs(); const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size); @@ -514,11 +514,11 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { } for (self.phdrs.items) |phdr| { - if (phdr.p_type != @backingInt(elf.PT.LOAD)) continue; - const increased_size = padToIdeal(phdr.p_filesz); - const test_end = phdr.p_offset +| increased_size; + if (phdr.type != .LOAD) continue; + const increased_size = padToIdeal(phdr.filesz); + const test_end = phdr.offset +| increased_size; if (start < test_end) { - if (end > phdr.p_offset) return test_end; + if (end > phdr.offset) return test_end; if (test_end < std.math.maxInt(u64)) at_end = false; } } @@ -538,8 +538,8 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 { if (section.sh_offset < min_pos) min_pos = section.sh_offset; } for (self.phdrs.items) |phdr| { - if (phdr.p_offset <= start) continue; - if (phdr.p_offset < min_pos) min_pos = phdr.p_offset; + if (phdr.offset <= start) continue; + if (phdr.offset < min_pos) min_pos = phdr.offset; } return min_pos - start; } @@ -1471,8 +1471,8 @@ fn writePhdrTable(self: *Elf) !void { const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?]; log.debug("writing program headers from 0x{x} to 0x{x}", .{ - phdr_table.p_offset, - phdr_table.p_offset + phdr_table.p_filesz, + phdr_table.offset, + phdr_table.offset + phdr_table.filesz, }); switch (self.ptr_width) { @@ -1486,19 +1486,19 @@ fn writePhdrTable(self: *Elf) !void { mem.byteSwapAllFields(elf.Elf32.Phdr, phdr); } } - try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset); + try self.pwriteAll(@ptrCast(buf), phdr_table.offset); }, .p64 => { - const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len); + const buf = try gpa.alloc(elf.Elf64.Phdr, self.phdrs.items.len); defer gpa.free(buf); for (buf, 0..) |*phdr, i| { phdr.* = self.phdrs.items[i]; if (foreign_endian) { - mem.byteSwapAllFields(elf.Elf64_Phdr, phdr); + mem.byteSwapAllFields(elf.Elf64.Phdr, phdr); } } - try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset); + try self.pwriteAll(@ptrCast(buf), phdr_table.offset); }, } } @@ -1581,7 +1581,7 @@ pub fn writeElfHeader(self: *Elf) !void { const entry_sym = obj.entrySymbol(self) orelse break :blk 0; break :blk @intCast(entry_sym.address(.{}, self)); } else 0; - const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].p_offset else 0; + const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].offset else 0; switch (self.ptr_width) { .p32 => { mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian); @@ -1623,7 +1623,7 @@ pub fn writeElfHeader(self: *Elf) !void { const e_phentsize: u16 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32.Phdr), - .p64 => @sizeOf(elf.Elf64_Phdr), + .p64 => @sizeOf(elf.Elf64.Phdr), }; mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian); index += 2; @@ -2260,15 +2260,15 @@ fn setHashSections(self: *Elf) !void { } } -fn phdrRank(phdr: elf.Elf64_Phdr) u8 { - return switch (phdr.p_type) { - @backingInt(elf.PT.NULL) => 0, - @backingInt(elf.PT.PHDR) => 1, - @backingInt(elf.PT.INTERP) => 2, - @backingInt(elf.PT.LOAD) => 3, - @backingInt(elf.PT.DYNAMIC), @backingInt(elf.PT.TLS) => 4, - @backingInt(elf.PT.GNU_EH_FRAME) => 5, - @backingInt(elf.PT.GNU_STACK) => 6, +fn phdrRank(phdr: elf.Elf64.Phdr) u8 { + return switch (phdr.type) { + .NULL => 0, + .PHDR => 1, + .INTERP => 2, + .LOAD => 3, + .DYNAMIC, .TLS => 4, + .GNU_EH_FRAME => 5, + .GNU_STACK => 6, else => 7, }; } @@ -2282,12 +2282,12 @@ fn sortPhdrs( const Entry = struct { phndx: u16, - pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool { + pub fn lessThan(program_headers: []const elf.Elf64.Phdr, lhs: @This(), rhs: @This()) bool { const lhs_phdr = program_headers[lhs.phndx]; const rhs_phdr = program_headers[rhs.phndx]; const lhs_rank = phdrRank(lhs_phdr); const rhs_rank = phdrRank(rhs_phdr); - if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr; + if (lhs_rank == rhs_rank) return lhs_phdr.vaddr < rhs_phdr.vaddr; return lhs_rank < rhs_rank; } }; @@ -2299,7 +2299,7 @@ fn sortPhdrs( } // The `@as` here works around a bug in the C backend. - mem.sort(Entry, entries, @as([]const elf.Elf64_Phdr, phdrs.items), Entry.lessThan); + mem.sort(Entry, entries, @as([]const elf.Elf64.Phdr, phdrs.items), Entry.lessThan); const backlinks = try gpa.alloc(u16, entries.len); defer gpa.free(backlinks); @@ -2673,10 +2673,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { }; const phsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32.Phdr), - .p64 => @sizeOf(elf.Elf64_Phdr), + .p64 => @sizeOf(elf.Elf64.Phdr), }; const needed_size = self.phdrs.items.len * phsize; - const available_space = self.allocatedSize(phdr_table.p_offset); + const available_space = self.allocatedSize(phdr_table.offset); if (needed_size > available_space) { // In this case, we have two options: @@ -2689,10 +2689,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space }); } - phdr_table_load.p_filesz = needed_size + ehsize; - phdr_table_load.p_memsz = needed_size + ehsize; - phdr_table.p_filesz = needed_size; - phdr_table.p_memsz = needed_size; + phdr_table_load.filesz = needed_size + ehsize; + phdr_table_load.memsz = needed_size + ehsize; + phdr_table.filesz = needed_size; + phdr_table.memsz = needed_size; } /// Allocates alloc sections and creates load segments for sections @@ -2758,7 +2758,7 @@ pub fn allocateAllocSections(self: *Elf) !void { // of any section that is contained in a cover and use it to align // the start address of the segement (and first section). const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?]; - var addr = phdr_table.p_vaddr + phdr_table.p_memsz; + var addr = phdr_table.vaddr + phdr_table.memsz; for (covers) |cover| { if (cover.items.len == 0) continue; @@ -2819,12 +2819,12 @@ pub fn allocateAllocSections(self: *Elf) !void { const first = slice.items(.shdr)[cover.items[0]]; const phndx = self.getPhdr(.{ .type = @backingInt(elf.PT.LOAD), .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?; const phdr = &self.phdrs.items[phndx.int()]; - const allocated_size = self.allocatedSize(phdr.p_offset); + const allocated_size = self.allocatedSize(phdr.offset); if (filesz > allocated_size) { - const old_offset = phdr.p_offset; - phdr.p_offset = 0; + const old_offset = phdr.offset; + phdr.offset = 0; var new_offset = try self.findFreeSpace(filesz, @"align"); - phdr.p_offset = new_offset; + phdr.offset = new_offset; log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset }); @@ -2854,11 +2854,11 @@ pub fn allocateAllocSections(self: *Elf) !void { } } - phdr.p_vaddr = first.sh_addr; - phdr.p_paddr = first.sh_addr; - phdr.p_memsz = memsz; - phdr.p_filesz = filesz; - phdr.p_align = @"align"; + phdr.vaddr = first.sh_addr; + phdr.paddr = first.sh_addr; + phdr.memsz = memsz; + phdr.filesz = filesz; + phdr.@"align" = @"align"; addr = mem.alignForward(u64, addr, self.page_size); } @@ -2902,12 +2902,12 @@ fn allocateSpecialPhdrs(self: *Elf) void { if (pair[0].int()) |index| { const shdr = slice.items(.shdr)[pair[1].?]; const phdr = &self.phdrs.items[index]; - phdr.p_align = shdr.sh_addralign; - phdr.p_offset = shdr.sh_offset; - phdr.p_vaddr = shdr.sh_addr; - phdr.p_paddr = shdr.sh_addr; - phdr.p_filesz = shdr.sh_size; - phdr.p_memsz = shdr.sh_size; + phdr.@"align" = shdr.sh_addralign; + phdr.offset = shdr.sh_offset; + phdr.vaddr = shdr.sh_addr; + phdr.paddr = shdr.sh_addr; + phdr.filesz = shdr.sh_size; + phdr.memsz = shdr.sh_size; } } @@ -2924,25 +2924,25 @@ fn allocateSpecialPhdrs(self: *Elf) void { shndx += 1; continue; } - phdr.p_offset = shdr.sh_offset; - phdr.p_vaddr = shdr.sh_addr; - phdr.p_paddr = shdr.sh_addr; - phdr.p_align = shdr.sh_addralign; + phdr.offset = shdr.sh_offset; + phdr.vaddr = shdr.sh_addr; + phdr.paddr = shdr.sh_addr; + phdr.@"align" = shdr.sh_addralign; shndx += 1; - phdr.p_align = @max(phdr.p_align, shdr.sh_addralign); + phdr.@"align" = @max(phdr.@"align", shdr.sh_addralign); if (shdr.sh_type != elf.SHT_NOBITS) { - phdr.p_filesz = shdr.sh_offset + shdr.sh_size - phdr.p_offset; + phdr.filesz = shdr.sh_offset + shdr.sh_size - phdr.offset; } - phdr.p_memsz = shdr.sh_addr + shdr.sh_size - phdr.p_vaddr; + phdr.memsz = shdr.sh_addr + shdr.sh_size - phdr.vaddr; while (shndx < shdrs.len) : (shndx += 1) { const next = shdrs[shndx]; if (next.sh_flags & elf.SHF_TLS == 0) break; - phdr.p_align = @max(phdr.p_align, next.sh_addralign); + phdr.@"align" = @max(phdr.@"align", next.sh_addralign); if (next.sh_type != elf.SHT_NOBITS) { - phdr.p_filesz = next.sh_offset + next.sh_size - phdr.p_offset; + phdr.filesz = next.sh_offset + next.sh_size - phdr.offset; } - phdr.p_memsz = next.sh_addr + next.sh_size - phdr.p_vaddr; + phdr.memsz = next.sh_addr + next.sh_size - phdr.vaddr; } } } @@ -3347,16 +3347,16 @@ pub fn archPtrWidthBytes(self: Elf) u8 { return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8)); } -fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32.Phdr { +fn phdrTo32(phdr: elf.Elf64.Phdr) elf.Elf32.Phdr { return .{ - .type = @fromBackingInt(phdr.p_type), - .flags = @fromBackingInt(phdr.p_flags), - .offset = @intCast(phdr.p_offset), - .vaddr = @intCast(phdr.p_vaddr), - .paddr = @intCast(phdr.p_paddr), - .filesz = @intCast(phdr.p_filesz), - .memsz = @intCast(phdr.p_memsz), - .@"align" = @intCast(phdr.p_align), + .type = phdr.type, + .flags = phdr.flags, + .offset = @intCast(phdr.offset), + .vaddr = @intCast(phdr.vaddr), + .paddr = @intCast(phdr.paddr), + .filesz = @intCast(phdr.filesz), + .memsz = @intCast(phdr.memsz), + .@"align" = @intCast(phdr.@"align"), }; } @@ -3397,7 +3397,7 @@ fn getPhdr(self: *Elf, opts: struct { if (self.phdr_indexes.table_load.int()) |index| { if (phndx == index) continue; } - if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) + if (@backingInt(phdr.type) == opts.type and @backingInt(phdr.flags) == opts.flags) return @fromBackingInt(@intCast(phndx)); } return .none; @@ -3415,14 +3415,14 @@ fn addPhdr(self: *Elf, opts: struct { const gpa = self.base.comp.gpa; const index: ProgramHeaderIndex = @fromBackingInt(@intCast(self.phdrs.items.len)); try self.phdrs.append(gpa, .{ - .p_type = opts.type, - .p_flags = opts.flags, - .p_offset = opts.offset, - .p_vaddr = opts.addr, - .p_paddr = opts.addr, - .p_filesz = opts.filesz, - .p_memsz = opts.memsz, - .p_align = opts.@"align", + .type = @fromBackingInt(opts.type), + .flags = @fromBackingInt(opts.flags), + .offset = opts.offset, + .vaddr = opts.addr, + .paddr = opts.addr, + .filesz = opts.filesz, + .memsz = opts.memsz, + .@"align" = opts.@"align", }); return index; } @@ -3673,9 +3673,9 @@ pub fn tpAddress(self: *Elf) i64 { const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; const addr = switch (self.getTarget().cpu.arch) { - .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), - .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), - .riscv64, .riscv64be => phdr.p_vaddr, + .x86_64 => mem.alignForward(u64, phdr.vaddr + phdr.memsz, phdr.@"align"), + .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.vaddr - 16, phdr.@"align"), + .riscv64, .riscv64be => phdr.vaddr, else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}), }; return @intCast(addr); @@ -3684,13 +3684,13 @@ pub fn tpAddress(self: *Elf) i64 { pub fn dtpAddress(self: *Elf) i64 { const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; - return @intCast(phdr.p_vaddr); + return @intCast(phdr.vaddr); } pub fn tlsAddress(self: *Elf) i64 { const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; - return @intCast(phdr.p_vaddr); + return @intCast(phdr.vaddr); } pub fn getShString(self: Elf, off: u32) [:0]const u8 { @@ -3886,10 +3886,10 @@ fn formatShdrFlags(sh_flags: u64, writer: *std.Io.Writer) std.Io.Writer.Error!vo const FormatPhdr = struct { elf_file: *Elf, - phdr: elf.Elf64_Phdr, + phdr: elf.Elf64.Phdr, }; -fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) { +fn fmtPhdr(self: *Elf, phdr: elf.Elf64.Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) { return .{ .data = .{ .phdr = phdr, .elf_file = self, @@ -3898,28 +3898,28 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void { const phdr = ctx.phdr; - const write = phdr.p_flags & elf.PF_W != 0; - const read = phdr.p_flags & elf.PF_R != 0; - const exec = phdr.p_flags & elf.PF_X != 0; + const write = phdr.flags.W; + const read = phdr.flags.R; + const exec = phdr.flags.X; var flags: [3]u8 = @splat('_'); if (exec) flags[0] = 'X'; if (write) flags[1] = 'W'; if (read) flags[2] = 'R'; - const p_type = switch (phdr.p_type) { - @backingInt(elf.PT.LOAD) => "LOAD", - @backingInt(elf.PT.TLS) => "TLS", - @backingInt(elf.PT.GNU_EH_FRAME) => "GNU_EH_FRAME", - @backingInt(elf.PT.GNU_STACK) => "GNU_STACK", - @backingInt(elf.PT.DYNAMIC) => "DYNAMIC", - @backingInt(elf.PT.INTERP) => "INTERP", - @backingInt(elf.PT.NULL) => "NULL", - @backingInt(elf.PT.PHDR) => "PHDR", - @backingInt(elf.PT.NOTE) => "NOTE", + const p_type = switch (phdr.type) { + .LOAD => "LOAD", + .TLS => "TLS", + .GNU_EH_FRAME => "GNU_EH_FRAME", + .GNU_STACK => "GNU_STACK", + .DYNAMIC => "DYNAMIC", + .INTERP => "INTERP", + .NULL => "NULL", + .PHDR => "PHDR", + .NOTE => "NOTE", else => "UNKNOWN", }; try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{ - p_type, flags, phdr.p_offset, phdr.p_vaddr, - phdr.p_align, phdr.p_filesz, phdr.p_memsz, + p_type, flags, phdr.offset, phdr.vaddr, + phdr.@"align", phdr.filesz, phdr.memsz, }); } -- 2.54.0 From 9bc9544bc8df2b0fe5ad82bd5459a9ce7ca55bac Mon Sep 17 00:00:00 2001 From: David Senoner Date: Thu, 30 Jul 2026 21:05:04 +0200 Subject: [PATCH 080/215] elf: remove deprecated Phdr structs --- lib/std/elf.zig | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index f2741734812a488ee400a82b7d7c4e159b61baaa..e4e905cea761ff6cbfbc81bcbd2fc44fdc8704ad 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -1235,28 +1235,6 @@ pub const Elf64_Ehdr = extern struct { e_shnum: Half, e_shstrndx: Half, }; -/// Deprecated, use `std.elf.Elf32.Phdr` -pub const Elf32_Phdr = extern struct { - p_type: Word, - p_offset: Elf32_Off, - p_vaddr: Elf32_Addr, - p_paddr: Elf32_Addr, - p_filesz: Word, - p_memsz: Word, - p_flags: Word, - p_align: Word, -}; -/// Deprecated, use `std.elf.Elf64.Phdr` -pub const Elf64_Phdr = extern struct { - p_type: Word, - p_flags: Word, - p_offset: Elf64_Off, - p_vaddr: Elf64_Addr, - p_paddr: Elf64_Addr, - p_filesz: Elf64_Xword, - p_memsz: Elf64_Xword, - p_align: Elf64_Xword, -}; /// Deprecated, use `std.elf.Elf32.Shdr` pub const Elf32_Shdr = extern struct { sh_name: Word, @@ -1527,12 +1505,6 @@ pub const Ehdr = switch (@sizeOf(usize)) { 8 => Elf64_Ehdr, else => @compileError("expected pointer size of 32 or 64"), }; -/// Deprecated, use `std.elf.ElfN.Phdr` -pub const Phdr = switch (@sizeOf(usize)) { - 4 => Elf32_Phdr, - 8 => Elf64_Phdr, - else => @compileError("expected pointer size of 32 or 64"), -}; pub const Dyn = switch (@sizeOf(usize)) { 4 => Elf32_Dyn, 8 => Elf64_Dyn, -- 2.54.0 From 159e4397fccf89af919d351945edb09af6a73165 Mon Sep 17 00:00:00 2001 From: whatisaphone Date: Fri, 24 Jul 2026 16:25:08 -0400 Subject: [PATCH 081/215] Remove redundant case --- lib/std/zig.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 4c41d56845f7ebd32bb83a51d2ec182b7e4e7154..0b798195f4f160013df7da9d76d6f2e3ea20499e 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -545,8 +545,7 @@ pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void { '\t' => try w.writeAll("\\t"), '\\' => try w.writeAll("\\\\"), '"' => try w.writeAll("\\\""), - '\'' => try w.writeByte('\''), - ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), + ' ', '!', '#'...'[', ']'...'~' => try w.writeByte(byte), else => { try w.writeAll("\\x"); try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); -- 2.54.0 From f6366f65bcff9405e11aeb6b876211f33c0076a4 Mon Sep 17 00:00:00 2001 From: whatisaphone Date: Fri, 24 Jul 2026 16:38:48 -0400 Subject: [PATCH 082/215] Simplify return type of hexEscape --- lib/std/ascii.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig index e346e87eb6805c0328d909a1709223c628db5858..90fce8cb531c90659dccabb235b00c46e06bdfa1 100644 --- a/lib/std/ascii.zig +++ b/lib/std/ascii.zig @@ -511,11 +511,11 @@ pub const HexEscape = struct { }; /// Replaces non-ASCII bytes with hex escapes. -pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Alt(HexEscape, HexEscape.format) { - return .{ .data = .{ .bytes = bytes, .charset = switch (case) { +pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) HexEscape { + return .{ .bytes = bytes, .charset = switch (case) { .lower => HexEscape.lower_charset, .upper => HexEscape.upper_charset, - } } }; + } }; } test hexEscape { -- 2.54.0 From 23aa045ef4565f274e6407b1e49f3c59ae379a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 29 Jul 2026 09:22:00 +0200 Subject: [PATCH 083/215] libc: update glibc headers to 2.44 --- .../include/aarch64-linux-gnu/bits/hwcap.h | 19 +- .../aarch64-linux-gnu/bits/math-vector.h | 8 + .../aarch64-linux-gnu/bits/struct_stat.h | 127 --------- .../include/aarch64-linux-gnu/bits/timesize.h | 20 -- .../finclude/math-vector-fortran.h | 158 +++++------ .../aarch64-linux-gnu/gnu/lib-names-lp64.h | 1 + .../aarch64-linux-gnu/gnu/lib-names-lp64_be.h | 1 + .../include/arc-linux-gnu/bits/struct_stat.h | 127 --------- .../include/arc-linux-gnu/bits/timesize.h | 20 -- .../include/arc-linux-gnu/gnu/lib-names.h | 1 + .../include/csky-linux-gnu/gnu/lib-names.h | 3 +- lib/libc/include/generic-glibc/assert.h | 28 +- lib/libc/include/generic-glibc/bits/cloexec.h | 1 + .../include/generic-glibc/bits/fcntl-linux.h | 21 +- .../generic-glibc/bits/libm-simd-decl-stubs.h | 11 + .../include/generic-glibc/bits/long-double.h | 9 +- .../include/generic-glibc/bits/mathcalls.h | 1 + lib/libc/include/generic-glibc/bits/sched.h | 3 + .../include/generic-glibc/bits/struct_stat.h | 264 +++++------------- lib/libc/include/generic-glibc/bits/syscall.h | 16 +- .../include/generic-glibc/bits/timesize.h | 8 +- lib/libc/include/generic-glibc/bits/uio-ext.h | 1 + lib/libc/include/generic-glibc/dlfcn.h | 7 +- lib/libc/include/generic-glibc/elf.h | 8 +- lib/libc/include/generic-glibc/features.h | 4 +- lib/libc/include/generic-glibc/fts.h | 126 ++++++++- .../include/generic-glibc/gnu/lib-names-32.h | 1 + .../generic-glibc/gnu/lib-names-hard.h | 1 + .../generic-glibc/gnu/lib-names-n32_hard.h | 1 + .../generic-glibc/gnu/lib-names-n64_hard.h | 1 + .../generic-glibc/gnu/lib-names-o32_hard.h | 1 + .../generic-glibc/gnu/lib-names-o32_soft.h | 1 + .../generic-glibc/gnu/lib-names-soft.h | 1 + lib/libc/include/generic-glibc/netinet/in.h | 2 + lib/libc/include/generic-glibc/netinet/tcp.h | 27 +- lib/libc/include/generic-glibc/regex.h | 2 +- lib/libc/include/generic-glibc/spawn.h | 20 ++ lib/libc/include/generic-glibc/stdlib.h | 2 +- lib/libc/include/generic-glibc/sys/mount.h | 22 +- lib/libc/include/generic-glibc/sys/pidfd.h | 26 ++ .../include/loongarch-linux-gnu/bits/hwcap.h | 4 +- .../loongarch-linux-gnu/bits/long-double.h | 21 -- .../loongarch-linux-gnu/bits/struct_stat.h | 127 --------- .../loongarch-linux-gnu/bits/timesize.h | 20 -- .../loongarch-linux-gnu/bits/wordsize.h | 15 +- .../include/loongarch-linux-gnu/fpu_control.h | 9 + .../gnu/lib-names-ilp32d.h} | 6 +- .../gnu/lib-names-ilp32s.h} | 7 +- .../loongarch-linux-gnu/gnu/lib-names-lp64d.h | 1 + .../loongarch-linux-gnu/gnu/lib-names-lp64s.h | 1 + .../loongarch-linux-gnu/gnu/lib-names.h | 6 + .../gnu/stubs-ilp32d.h} | 5 + .../loongarch-linux-gnu/gnu/stubs-ilp32s.h | 38 +++ .../include/loongarch-linux-gnu/gnu/stubs.h | 6 + .../include/loongarch-linux-gnu/sys/asm.h | 38 ++- .../include/m68k-linux-gnu/gnu/lib-names.h | 1 + .../bits/long-double.h | 9 +- .../include/mips-linux-gnu/bits/struct_stat.h | 237 ++++++++++++++++ .../bits/timesize.h | 2 +- .../include/mips-linux-gnu/bits/waitstatus.h | 68 +++++ .../powerpc-linux-gnu/bits/long-double.h | 2 +- .../bits/ppc.h | 0 .../powerpc-linux-gnu/bits/struct_mutex.h | 2 +- .../powerpc-linux-gnu/gnu/lib-names-64-v2.h | 1 + .../sys/platform/ppc.h | 0 .../riscv-linux-gnu/bits/long-double.h | 21 -- .../riscv-linux-gnu/bits/struct_stat.h | 127 --------- .../include/riscv-linux-gnu/bits/timesize.h | 20 -- .../riscv-linux-gnu/gnu/lib-names-ilp32d.h | 1 + .../riscv-linux-gnu/gnu/lib-names-lp64d.h | 1 + .../include/s390x-linux-gnu/bits/elfclass.h | 7 +- .../s390x-linux-gnu/bits/environments.h | 96 ------- lib/libc/include/s390x-linux-gnu/bits/fcntl.h | 26 +- lib/libc/include/s390x-linux-gnu/bits/fenv.h | 8 +- lib/libc/include/s390x-linux-gnu/bits/link.h | 62 +--- .../s390x-linux-gnu/bits/procfs-extra.h | 75 ----- .../include/s390x-linux-gnu/bits/procfs-id.h | 30 -- .../include/s390x-linux-gnu/bits/setjmp.h | 6 - .../include/s390x-linux-gnu/bits/sigaction.h | 35 +-- .../s390x-linux-gnu/bits/struct_mutex.h | 26 +- .../s390x-linux-gnu/bits/struct_rwlock.h | 17 +- .../s390x-linux-gnu/bits/struct_stat.h | 120 +------- .../include/s390x-linux-gnu/bits/typesizes.h | 36 +-- lib/libc/include/s390x-linux-gnu/bits/utmp.h | 127 --------- lib/libc/include/s390x-linux-gnu/bits/utmpx.h | 106 ------- .../include/s390x-linux-gnu/bits/wordsize.h | 26 +- .../s390x-linux-gnu/gnu/lib-names-64.h | 27 -- .../include/s390x-linux-gnu/gnu/lib-names.h | 31 +- lib/libc/include/s390x-linux-gnu/gnu/stubs.h | 22 +- .../include/s390x-linux-gnu/sys/ucontext.h | 6 +- .../include/sparc-linux-gnu/bits/cloexec.h | 1 + .../sparc-linux-gnu/gnu/lib-names-64.h | 1 + .../gnu/stubs-64.h | 0 .../include/x86-linux-gnu/bits/struct_mutex.h | 2 +- .../include/x86-linux-gnu/gnu/lib-names-64.h | 1 + .../include/x86-linux-gnu/gnu/lib-names-x32.h | 1 + tools/process_headers.zig | 2 + 97 files changed, 1031 insertions(+), 1763 deletions(-) delete mode 100644 lib/libc/include/aarch64-linux-gnu/bits/struct_stat.h delete mode 100644 lib/libc/include/aarch64-linux-gnu/bits/timesize.h delete mode 100644 lib/libc/include/arc-linux-gnu/bits/struct_stat.h delete mode 100644 lib/libc/include/arc-linux-gnu/bits/timesize.h create mode 100644 lib/libc/include/generic-glibc/bits/cloexec.h delete mode 100644 lib/libc/include/loongarch-linux-gnu/bits/long-double.h delete mode 100644 lib/libc/include/loongarch-linux-gnu/bits/struct_stat.h delete mode 100644 lib/libc/include/loongarch-linux-gnu/bits/timesize.h rename lib/libc/include/{powerpc-linux-gnu/gnu/lib-names-32.h => loongarch-linux-gnu/gnu/lib-names-ilp32d.h} (80%) rename lib/libc/include/{powerpc-linux-gnu/gnu/lib-names-64-v1.h => loongarch-linux-gnu/gnu/lib-names-ilp32s.h} (80%) rename lib/libc/include/{powerpc-linux-gnu/gnu/stubs-64-v1.h => loongarch-linux-gnu/gnu/stubs-ilp32d.h} (71%) create mode 100644 lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32s.h rename lib/libc/include/{aarch64-linux-gnu => mips-linux-gnu}/bits/long-double.h (82%) create mode 100644 lib/libc/include/mips-linux-gnu/bits/struct_stat.h rename lib/libc/include/{s390x-linux-gnu => mips-linux-gnu}/bits/timesize.h (93%) create mode 100644 lib/libc/include/mips-linux-gnu/bits/waitstatus.h rename lib/libc/include/{generic-glibc => powerpc-linux-gnu}/bits/ppc.h (100%) rename lib/libc/include/{generic-glibc => powerpc-linux-gnu}/sys/platform/ppc.h (100%) delete mode 100644 lib/libc/include/riscv-linux-gnu/bits/long-double.h delete mode 100644 lib/libc/include/riscv-linux-gnu/bits/struct_stat.h delete mode 100644 lib/libc/include/riscv-linux-gnu/bits/timesize.h delete mode 100644 lib/libc/include/s390x-linux-gnu/bits/environments.h delete mode 100644 lib/libc/include/s390x-linux-gnu/bits/procfs-extra.h delete mode 100644 lib/libc/include/s390x-linux-gnu/bits/procfs-id.h delete mode 100644 lib/libc/include/s390x-linux-gnu/bits/utmp.h delete mode 100644 lib/libc/include/s390x-linux-gnu/bits/utmpx.h delete mode 100644 lib/libc/include/s390x-linux-gnu/gnu/lib-names-64.h create mode 100644 lib/libc/include/sparc-linux-gnu/bits/cloexec.h rename lib/libc/include/{generic-glibc => sparc-linux-gnu}/gnu/stubs-64.h (100%) diff --git a/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h b/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h index f4189aa1bfca6909be4967e00821932faf753c7a..ea1c9e30bc803d6c5eb0396d62a46707ca7bdddd 100644 --- a/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h +++ b/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h @@ -55,6 +55,21 @@ #define HWCAP_PACA (1 << 30) #define HWCAP_PACG (1UL << 31) #define HWCAP_GCS (1UL << 32) +#define HWCAP_CMPBR (1UL << 33) +#define HWCAP_FPRCVT (1UL << 34) +#define HWCAP_F8MM8 (1UL << 35) +#define HWCAP_F8MM4 (1UL << 36) +#define HWCAP_SVE_F16MM (1UL << 37) +#define HWCAP_SVE_ELTPERM (1UL << 38) +#define HWCAP_SVE_AES2 (1UL << 39) +#define HWCAP_SVE_BFSCALE (1UL << 40) +#define HWCAP_SVE2P2 (1UL << 41) +#define HWCAP_SME2P2 (1UL << 42) +#define HWCAP_SME_SBITPERM (1UL << 43) +#define HWCAP_SME_AES (1UL << 44) +#define HWCAP_SME_SFEXPA (1UL << 45) +#define HWCAP_SME_STMOP (1UL << 46) +#define HWCAP_SME_SMOP4 (1UL << 47) #define HWCAP2_DCPODP (1 << 0) #define HWCAP2_SVE2 (1 << 1) @@ -122,4 +137,6 @@ #define HWCAP2_POE (1UL << 63) #define HWCAP3_MTE_FAR (1UL << 0) -#define HWCAP3_MTE_STORE_ONLY (1UL << 1) \ No newline at end of file +#define HWCAP3_MTE_STORE_ONLY (1UL << 1) +#define HWCAP3_LSFE (1UL << 2) +#define HWCAP3_LS64 (1UL << 3) \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/bits/math-vector.h b/lib/libc/include/aarch64-linux-gnu/bits/math-vector.h index 68043a976c58a8f126799f7c386006471a4996eb..c83fbc235bcaefcba343ec5122af94a316e67c57 100644 --- a/lib/libc/include/aarch64-linux-gnu/bits/math-vector.h +++ b/lib/libc/include/aarch64-linux-gnu/bits/math-vector.h @@ -157,6 +157,10 @@ # define __DECL_SIMD_pow __DECL_SIMD_aarch64 # undef __DECL_SIMD_powf # define __DECL_SIMD_powf __DECL_SIMD_aarch64 +# undef __DECL_SIMD_powr +# define __DECL_SIMD_powr __DECL_SIMD_aarch64 +# undef __DECL_SIMD_powrf +# define __DECL_SIMD_powrf __DECL_SIMD_aarch64 # undef __DECL_SIMD_rsqrt # define __DECL_SIMD_rsqrt __DECL_SIMD_aarch64 # undef __DECL_SIMD_rsqrtf @@ -243,6 +247,7 @@ __vpcs __f32x4_t _ZGVnN4v_log2f (__f32x4_t); __vpcs __f32x4_t _ZGVnN4v_log2p1f (__f32x4_t); __vpcs __f32x4_t _ZGVnN4v_logp1f (__f32x4_t); __vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t); +__vpcs __f32x4_t _ZGVnN4vv_powrf (__f32x4_t, __f32x4_t); __vpcs __f32x4_t _ZGVnN4v_rsqrtf (__f32x4_t); __vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t); __vpcs __f32x4_t _ZGVnN4v_sinhf (__f32x4_t); @@ -283,6 +288,7 @@ __vpcs __f64x2_t _ZGVnN2v_log2 (__f64x2_t); __vpcs __f64x2_t _ZGVnN2v_log2p1 (__f64x2_t); __vpcs __f64x2_t _ZGVnN2v_logp1 (__f64x2_t); __vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t); +__vpcs __f64x2_t _ZGVnN2vv_powr (__f64x2_t, __f64x2_t); __vpcs __f64x2_t _ZGVnN2v_rsqrt (__f64x2_t); __vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t); __vpcs __f64x2_t _ZGVnN2v_sinh (__f64x2_t); @@ -328,6 +334,7 @@ __sv_f32_t _ZGVsMxv_log2f (__sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxv_log2p1f (__sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxv_logp1f (__sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxvv_powf (__sv_f32_t, __sv_f32_t, __sv_bool_t); +__sv_f32_t _ZGVsMxvv_powrf (__sv_f32_t, __sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxv_rsqrtf (__sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxv_sinf (__sv_f32_t, __sv_bool_t); __sv_f32_t _ZGVsMxv_sinhf (__sv_f32_t, __sv_bool_t); @@ -368,6 +375,7 @@ __sv_f64_t _ZGVsMxv_log2 (__sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxv_log2p1 (__sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxv_logp1 (__sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxvv_pow (__sv_f64_t, __sv_f64_t, __sv_bool_t); +__sv_f64_t _ZGVsMxvv_powr (__sv_f64_t, __sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxv_rsqrt (__sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t); __sv_f64_t _ZGVsMxv_sinh (__sv_f64_t, __sv_bool_t); diff --git a/lib/libc/include/aarch64-linux-gnu/bits/struct_stat.h b/lib/libc/include/aarch64-linux-gnu/bits/struct_stat.h deleted file mode 100644 index 0462d37a6849812f485a6830a7c0dca303332636..0000000000000000000000000000000000000000 --- a/lib/libc/include/aarch64-linux-gnu/bits/struct_stat.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Definition for struct stat. - Copyright (C) 2020-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library. If not, see - . */ - -#if !defined _SYS_STAT_H && !defined _FCNTL_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_STRUCT_STAT_H -#define _BITS_STRUCT_STAT_H 1 - -#include -#include - -#if defined __USE_FILE_OFFSET64 -# define __field64(type, type64, name) type64 name -#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T -# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T -# error "ino_t and off_t must both be the same type" -# endif -# define __field64(type, type64, name) type name -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define __field64(type, type64, name) \ - type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad -#else -# define __field64(type, type64, name) \ - int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name -#endif - -struct stat - { - __dev_t st_dev; /* Device. */ - __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; - -#undef __field64 - -#ifdef __USE_LARGEFILE64 -struct stat64 - { - __dev_t st_dev; /* Device. */ - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __off64_t st_size; /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; -#endif - -/* Tell code we have these members. */ -#define _STATBUF_ST_BLKSIZE -#define _STATBUF_ST_RDEV -/* Nanosecond resolution time values are supported. */ -#define _STATBUF_ST_NSEC - -#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/bits/timesize.h b/lib/libc/include/aarch64-linux-gnu/bits/timesize.h deleted file mode 100644 index dff2da5ed6bf30ce6f5580aee352e0958d58b623..0000000000000000000000000000000000000000 --- a/lib/libc/include/aarch64-linux-gnu/bits/timesize.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Bit size of the time_t type at glibc build time, general case. - Copyright (C) 2018-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* Size in bits of the 'time_t' type of the default ABI. */ -#define __TIMESIZE 64 \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/finclude/math-vector-fortran.h b/lib/libc/include/aarch64-linux-gnu/finclude/math-vector-fortran.h index 59c7f2db4a8dfefe910714f9a659b8e61680df63..2af413c57c6ec176e65b5555ff2394df576a96c6 100644 --- a/lib/libc/include/aarch64-linux-gnu/finclude/math-vector-fortran.h +++ b/lib/libc/include/aarch64-linux-gnu/finclude/math-vector-fortran.h @@ -16,81 +16,83 @@ ! License along with the GNU C Library; if not, see ! . -!GCC$ builtin (acos) attributes simd (notinbranch) -!GCC$ builtin (acosf) attributes simd (notinbranch) -!GCC$ builtin (acosh) attributes simd (notinbranch) -!GCC$ builtin (acoshf) attributes simd (notinbranch) -!GCC$ builtin (acospi) attributes simd (notinbranch) -!GCC$ builtin (acospif) attributes simd (notinbranch) -!GCC$ builtin (asin) attributes simd (notinbranch) -!GCC$ builtin (asinf) attributes simd (notinbranch) -!GCC$ builtin (asinh) attributes simd (notinbranch) -!GCC$ builtin (asinhf) attributes simd (notinbranch) -!GCC$ builtin (asinpi) attributes simd (notinbranch) -!GCC$ builtin (asinpif) attributes simd (notinbranch) -!GCC$ builtin (atan) attributes simd (notinbranch) -!GCC$ builtin (atan2) attributes simd (notinbranch) -!GCC$ builtin (atan2f) attributes simd (notinbranch) -!GCC$ builtin (atan2pi) attributes simd (notinbranch) -!GCC$ builtin (atan2pif) attributes simd (notinbranch) -!GCC$ builtin (atanf) attributes simd (notinbranch) -!GCC$ builtin (atanh) attributes simd (notinbranch) -!GCC$ builtin (atanhf) attributes simd (notinbranch) -!GCC$ builtin (atanpi) attributes simd (notinbranch) -!GCC$ builtin (atanpif) attributes simd (notinbranch) -!GCC$ builtin (cbrt) attributes simd (notinbranch) -!GCC$ builtin (cbrtf) attributes simd (notinbranch) -!GCC$ builtin (cos) attributes simd (notinbranch) -!GCC$ builtin (cosf) attributes simd (notinbranch) -!GCC$ builtin (cosh) attributes simd (notinbranch) -!GCC$ builtin (coshf) attributes simd (notinbranch) -!GCC$ builtin (cospi) attributes simd (notinbranch) -!GCC$ builtin (cospif) attributes simd (notinbranch) -!GCC$ builtin (erf) attributes simd (notinbranch) -!GCC$ builtin (erfc) attributes simd (notinbranch) -!GCC$ builtin (erfcf) attributes simd (notinbranch) -!GCC$ builtin (erff) attributes simd (notinbranch) -!GCC$ builtin (exp) attributes simd (notinbranch) -!GCC$ builtin (exp10) attributes simd (notinbranch) -!GCC$ builtin (exp10f) attributes simd (notinbranch) -!GCC$ builtin (exp10m1) attributes simd (notinbranch) -!GCC$ builtin (exp10m1f) attributes simd (notinbranch) -!GCC$ builtin (exp2) attributes simd (notinbranch) -!GCC$ builtin (exp2f) attributes simd (notinbranch) -!GCC$ builtin (exp2m1) attributes simd (notinbranch) -!GCC$ builtin (exp2m1f) attributes simd (notinbranch) -!GCC$ builtin (expf) attributes simd (notinbranch) -!GCC$ builtin (expm1) attributes simd (notinbranch) -!GCC$ builtin (expm1f) attributes simd (notinbranch) -!GCC$ builtin (hypot) attributes simd (notinbranch) -!GCC$ builtin (hypotf) attributes simd (notinbranch) -!GCC$ builtin (log) attributes simd (notinbranch) -!GCC$ builtin (log10) attributes simd (notinbranch) -!GCC$ builtin (log10f) attributes simd (notinbranch) -!GCC$ builtin (log10p1) attributes simd (notinbranch) -!GCC$ builtin (log10p1f) attributes simd (notinbranch) -!GCC$ builtin (log1p) attributes simd (notinbranch) -!GCC$ builtin (log1pf) attributes simd (notinbranch) -!GCC$ builtin (log2) attributes simd (notinbranch) -!GCC$ builtin (log2f) attributes simd (notinbranch) -!GCC$ builtin (log2p1) attributes simd (notinbranch) -!GCC$ builtin (log2p1f) attributes simd (notinbranch) -!GCC$ builtin (logf) attributes simd (notinbranch) -!GCC$ builtin (logp1) attributes simd (notinbranch) -!GCC$ builtin (logp1f) attributes simd (notinbranch) -!GCC$ builtin (pow) attributes simd (notinbranch) -!GCC$ builtin (powf) attributes simd (notinbranch) -!GCC$ builtin (rsqrt) attributes simd (notinbranch) -!GCC$ builtin (rsqrtf) attributes simd (notinbranch) -!GCC$ builtin (sin) attributes simd (notinbranch) -!GCC$ builtin (sinf) attributes simd (notinbranch) -!GCC$ builtin (sinh) attributes simd (notinbranch) -!GCC$ builtin (sinhf) attributes simd (notinbranch) -!GCC$ builtin (sinpi) attributes simd (notinbranch) -!GCC$ builtin (sinpif) attributes simd (notinbranch) -!GCC$ builtin (tan) attributes simd (notinbranch) -!GCC$ builtin (tanf) attributes simd (notinbranch) -!GCC$ builtin (tanh) attributes simd (notinbranch) -!GCC$ builtin (tanhf) attributes simd (notinbranch) -!GCC$ builtin (tanpi) attributes simd (notinbranch) -!GCC$ builtin (tanpif) attributes simd (notinbranch) \ No newline at end of file +!GCC$ builtin (acos) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (acosf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (acosh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (acoshf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (acospi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (acospif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asin) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asinf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asinh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asinhf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asinpi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (asinpif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atan) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atan2) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atan2f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atan2pi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atan2pif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atanf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atanh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atanhf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atanpi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (atanpif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cbrt) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cbrtf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cos) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cosf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cosh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (coshf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cospi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (cospif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (erf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (erfc) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (erfcf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (erff) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp10) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp10f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp10m1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp10m1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp2) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp2f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp2m1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (exp2m1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (expf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (expm1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (expm1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (hypot) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (hypotf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log10) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log10f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log10p1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log10p1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log1p) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log1pf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log2) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log2f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log2p1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (log2p1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (logf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (logp1) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (logp1f) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (pow) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (powf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (powr) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (powrf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (rsqrt) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (rsqrtf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sin) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sinf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sinh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sinhf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sinpi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (sinpif) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tan) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tanf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tanh) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tanhf) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tanpi) attributes simd (notinbranch) if('fastmath') +!GCC$ builtin (tanpif) attributes simd (notinbranch) if('fastmath') \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64.h b/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64.h index e34eb75134323543b3d8d8807e0bc3c7a3c31abd..46acbc27479223aa3abfe70175255d2b346e9cac 100644 --- a/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64.h +++ b/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64_be.h b/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64_be.h index 2fba436ba35ca351e3c28abeda69028774654a92..ad55fcf123ad4488d626ece14689abda37598381 100644 --- a/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64_be.h +++ b/lib/libc/include/aarch64-linux-gnu/gnu/lib-names-lp64_be.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/arc-linux-gnu/bits/struct_stat.h b/lib/libc/include/arc-linux-gnu/bits/struct_stat.h deleted file mode 100644 index 0462d37a6849812f485a6830a7c0dca303332636..0000000000000000000000000000000000000000 --- a/lib/libc/include/arc-linux-gnu/bits/struct_stat.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Definition for struct stat. - Copyright (C) 2020-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library. If not, see - . */ - -#if !defined _SYS_STAT_H && !defined _FCNTL_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_STRUCT_STAT_H -#define _BITS_STRUCT_STAT_H 1 - -#include -#include - -#if defined __USE_FILE_OFFSET64 -# define __field64(type, type64, name) type64 name -#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T -# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T -# error "ino_t and off_t must both be the same type" -# endif -# define __field64(type, type64, name) type name -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define __field64(type, type64, name) \ - type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad -#else -# define __field64(type, type64, name) \ - int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name -#endif - -struct stat - { - __dev_t st_dev; /* Device. */ - __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; - -#undef __field64 - -#ifdef __USE_LARGEFILE64 -struct stat64 - { - __dev_t st_dev; /* Device. */ - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __off64_t st_size; /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; -#endif - -/* Tell code we have these members. */ -#define _STATBUF_ST_BLKSIZE -#define _STATBUF_ST_RDEV -/* Nanosecond resolution time values are supported. */ -#define _STATBUF_ST_NSEC - -#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/arc-linux-gnu/bits/timesize.h b/lib/libc/include/arc-linux-gnu/bits/timesize.h deleted file mode 100644 index dff2da5ed6bf30ce6f5580aee352e0958d58b623..0000000000000000000000000000000000000000 --- a/lib/libc/include/arc-linux-gnu/bits/timesize.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Bit size of the time_t type at glibc build time, general case. - Copyright (C) 2018-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* Size in bits of the 'time_t' type of the default ABI. */ -#define __TIMESIZE 64 \ No newline at end of file diff --git a/lib/libc/include/arc-linux-gnu/gnu/lib-names.h b/lib/libc/include/arc-linux-gnu/gnu/lib-names.h index 68bed2a1a178f5003654ea064883559b08d5242e..5e617b3a49ddd6da357923e3cfdae83ef4a189fb 100644 --- a/lib/libc/include/arc-linux-gnu/gnu/lib-names.h +++ b/lib/libc/include/arc-linux-gnu/gnu/lib-names.h @@ -25,6 +25,7 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" #endif /* gnu/lib-names.h */ \ No newline at end of file diff --git a/lib/libc/include/csky-linux-gnu/gnu/lib-names.h b/lib/libc/include/csky-linux-gnu/gnu/lib-names.h index fbe1a718fbeb97c65267676396b656897ac0b648..f63e5133babbdfd1309f38fe281c0d29c1ef8a64 100644 --- a/lib/libc/include/csky-linux-gnu/gnu/lib-names.h +++ b/lib/libc/include/csky-linux-gnu/gnu/lib-names.h @@ -31,6 +31,7 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" -#endif /* gnu/lib-names.h */ +#endif /* gnu/lib-names.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/assert.h b/lib/libc/include/generic-glibc/assert.h index 73562fec4b9cf794aeb03cc1f3e4c5988eeb42cf..11c3cec04420eb0925d865ed489f911f4e29de37 100644 --- a/lib/libc/include/generic-glibc/assert.h +++ b/lib/libc/include/generic-glibc/assert.h @@ -52,13 +52,12 @@ comma in the initializer list, can be passed to assert. This depends on support for variadic macros (added in C99 and GCC 2.95), and on support for _Bool (added in C99 and GCC 3.0) in order to - validate that only a single expression is passed as an argument, - and is currently implemented only for C. */ -#if (__GLIBC_USE (ISOC23) \ - && (defined __GNUC__ \ - ? __GNUC_PREREQ (3, 0) \ - : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \ - && !defined __cplusplus) + validate that only a single expression is passed as an argument. */ +#if ((__GLIBC_USE (ISOC23) \ + && (defined __GNUC__ \ + ? __GNUC_PREREQ (3, 0) \ + : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) \ + || (defined __cplusplus && __cplusplus > 202302L)) # define __ASSERT_VARIADIC 1 #else # define __ASSERT_VARIADIC 0 @@ -108,7 +107,7 @@ extern void __assert (const char *__assertion, const char *__file, int __line) __THROW __attribute__ ((__noreturn__)) __COLD; -# if __ASSERT_VARIADIC +# if __ASSERT_VARIADIC && !defined __cplusplus /* This function is not defined and is not called outside of an unevaluated sizeof, but serves to verify that the argument to assert is a single expression. */ @@ -131,11 +130,22 @@ __END_DECLS # define __ASSERT_FILE __FILE__ # define __ASSERT_LINE __LINE__ # endif -# define assert(expr) \ +# if __ASSERT_VARIADIC +/* The first test of __VA_ARGS__ evaluates it without converting scoped + enumeration values to bool, and the second test checks that it is a + single expression without evaluating it. */ +# define assert(...) \ + ((__VA_ARGS__) \ + ? void (1 ? 1 : bool (__VA_ARGS__)) \ + : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE, \ + __ASSERT_FUNCTION)) +# else +# define assert(expr) \ (static_cast (expr) \ ? void (0) \ : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \ __ASSERT_FUNCTION)) +# endif # elif !defined __GNUC__ || defined __STRICT_ANSI__ # if __ASSERT_VARIADIC # define assert(...) \ diff --git a/lib/libc/include/generic-glibc/bits/cloexec.h b/lib/libc/include/generic-glibc/bits/cloexec.h new file mode 100644 index 0000000000000000000000000000000000000000..030893ff8723fd0d1dfe500c88bbc290d01cc292 --- /dev/null +++ b/lib/libc/include/generic-glibc/bits/cloexec.h @@ -0,0 +1 @@ +#define __O_CLOEXEC 02000000 \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/fcntl-linux.h b/lib/libc/include/generic-glibc/bits/fcntl-linux.h index b6a2979287a93d686f1ca0b44b9faf511eea6b9f..894a22c8ba99c3a72413feca4dcf25c676177510 100644 --- a/lib/libc/include/generic-glibc/bits/fcntl-linux.h +++ b/lib/libc/include/generic-glibc/bits/fcntl-linux.h @@ -81,9 +81,7 @@ #ifndef __O_NOFOLLOW # define __O_NOFOLLOW 0400000 #endif -#ifndef __O_CLOEXEC -# define __O_CLOEXEC 02000000 -#endif +#include #ifndef __O_DIRECT # define __O_DIRECT 040000 #endif @@ -176,8 +174,8 @@ #endif #if defined __USE_UNIX98 || defined __USE_XOPEN2K8 -# define F_SETOWN __F_SETOWN /* Get owner (process receiving SIGIO). */ -# define F_GETOWN __F_GETOWN /* Set owner (process receiving SIGIO). */ +# define F_SETOWN __F_SETOWN /* Set owner (process receiving SIGIO). */ +# define F_GETOWN __F_GETOWN /* Get owner (process receiving SIGIO). */ #endif #ifndef __F_SETSIG @@ -185,15 +183,15 @@ # define __F_GETSIG 11 /* Get number of signal to be sent. */ #endif #ifndef __F_SETOWN_EX -# define __F_SETOWN_EX 15 /* Get owner (thread receiving SIGIO). */ -# define __F_GETOWN_EX 16 /* Set owner (thread receiving SIGIO). */ +# define __F_SETOWN_EX 15 /* Set owner (thread receiving SIGIO). */ +# define __F_GETOWN_EX 16 /* Get owner (thread receiving SIGIO). */ #endif #ifdef __USE_GNU # define F_SETSIG __F_SETSIG /* Set number of signal to be sent. */ # define F_GETSIG __F_GETSIG /* Get number of signal to be sent. */ -# define F_SETOWN_EX __F_SETOWN_EX /* Get owner (thread receiving SIGIO). */ -# define F_GETOWN_EX __F_GETOWN_EX /* Set owner (thread receiving SIGIO). */ +# define F_SETOWN_EX __F_SETOWN_EX /* Set owner (thread receiving SIGIO). */ +# define F_GETOWN_EX __F_GETOWN_EX /* Get owner (thread receiving SIGIO). */ #endif #ifdef __USE_GNU @@ -203,7 +201,7 @@ # define F_DUPFD_QUERY 1027 /* Compare two file descriptors for sameness. */ # define F_CREATED_QUERY 1028 /* Was the file just created? */ # define F_SETPIPE_SZ 1031 /* Set pipe page size array. */ -# define F_GETPIPE_SZ 1032 /* Set pipe page size array. */ +# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */ # define F_ADD_SEALS 1033 /* Add seals to file. */ # define F_GET_SEALS 1034 /* Get seals for file. */ /* Set / get write life time hints. */ @@ -211,6 +209,8 @@ # define F_SET_RW_HINT 1036 # define F_GET_FILE_RW_HINT 1037 # define F_SET_FILE_RW_HINT 1038 +# define F_GETDELEG 1039 /* Get delegation. */ +# define F_SETDELEG 1040 /* Set delegation. */ #endif #ifdef __USE_XOPEN2K8 # define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with @@ -221,6 +221,7 @@ #define FD_CLOEXEC 1 /* Actually anything with low bit set goes */ #ifdef __USE_GNU # define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */ +# define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */ #endif #ifndef F_RDLCK diff --git a/lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h b/lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h index d3b43f59cc01e21655c009ec365eb49b30d15e03..1ae3bf4992d67a9881cd05ea47f64dc4c752ec0c 100644 --- a/lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h +++ b/lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h @@ -99,6 +99,17 @@ #define __DECL_SIMD_powf64x #define __DECL_SIMD_powf128x +#define __DECL_SIMD_powr +#define __DECL_SIMD_powrf +#define __DECL_SIMD_powrl +#define __DECL_SIMD_powrf16 +#define __DECL_SIMD_powrf32 +#define __DECL_SIMD_powrf64 +#define __DECL_SIMD_powrf128 +#define __DECL_SIMD_powrf32x +#define __DECL_SIMD_powrf64x +#define __DECL_SIMD_powrf128x + #define __DECL_SIMD_acos #define __DECL_SIMD_acosf #define __DECL_SIMD_acosl diff --git a/lib/libc/include/generic-glibc/bits/long-double.h b/lib/libc/include/generic-glibc/bits/long-double.h index ebf6ac878fbf42241d0b2bcaf8c6049d08d827c5..af7784dbe6dd85cd9538b5a7b437ab45de22eeb8 100644 --- a/lib/libc/include/generic-glibc/bits/long-double.h +++ b/lib/libc/include/generic-glibc/bits/long-double.h @@ -1,4 +1,4 @@ -/* Properties of long double type. MIPS version. +/* Properties of long double type. ldbl-128 version. Copyright (C) 2016-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,9 +16,6 @@ License along with the GNU C Library; if not, see . */ -#include - -#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32 -# define __NO_LONG_DOUBLE_MATH 1 -#endif +/* long double is distinct from double, so there is nothing to + define here. */ #define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0 \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/mathcalls.h b/lib/libc/include/generic-glibc/bits/mathcalls.h index 7ff83e5acbeebe7f5fd3b1185735822e436aa5dd..740f26aed89b757cbe7f58e6d4f8570e6dfa74a3 100644 --- a/lib/libc/include/generic-glibc/bits/mathcalls.h +++ b/lib/libc/include/generic-glibc/bits/mathcalls.h @@ -197,6 +197,7 @@ __MATHCALL (compoundn,, (_Mdouble_ __x, long long int __y)); __MATHCALL (pown,, (_Mdouble_ __x, long long int __y)); /* Return X to the Y power. */ +__MATHCALL_VEC (powr,, (_Mdouble_ __x, _Mdouble_ __y)); __MATHCALL (powr,, (_Mdouble_ __x, _Mdouble_ __y)); /* Return the Yth root of X. */ diff --git a/lib/libc/include/generic-glibc/bits/sched.h b/lib/libc/include/generic-glibc/bits/sched.h index aa49876c1c353c46701b02b6f7f19b2f565e06e5..a66bfd53a14ce66651062a7ea51673c6e867e863 100644 --- a/lib/libc/include/generic-glibc/bits/sched.h +++ b/lib/libc/include/generic-glibc/bits/sched.h @@ -54,6 +54,9 @@ #define SCHED_FLAG_UTIL_CLAMP \ (SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX) +/* Flags for the flags argument of sched_getattr. */ +#define SCHED_GETATTR_FLAG_DL_DYNAMIC 0x01 + /* Use "" to work around incorrect macro expansion of the __has_include argument (GCC PR 80005). */ # ifdef __has_include diff --git a/lib/libc/include/generic-glibc/bits/struct_stat.h b/lib/libc/include/generic-glibc/bits/struct_stat.h index 231c875e7ab2c703e50746e2191ddc411c0878a2..0462d37a6849812f485a6830a7c0dca303332636 100644 --- a/lib/libc/include/generic-glibc/bits/struct_stat.h +++ b/lib/libc/include/generic-glibc/bits/struct_stat.h @@ -23,215 +23,105 @@ #ifndef _BITS_STRUCT_STAT_H #define _BITS_STRUCT_STAT_H 1 -#include - -#if _MIPS_SIM == _ABIO32 -/* Structure describing file characteristics. */ -struct stat - { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - unsigned long int st_dev; - long int st_pad1[3]; -# ifndef __USE_FILE_OFFSET64 - __ino_t st_ino; /* File serial number. */ -# else - __ino64_t st_ino; /* File serial number. */ -# endif - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - unsigned long int st_rdev; /* Device number, if device. */ -# ifndef __USE_FILE_OFFSET64 - long int st_pad2[2]; - __off_t st_size; /* Size of file, in bytes. */ - /* SVR4 added this extra long to allow for expansion of off_t. */ - long int st_pad3; -# else - long int st_pad2[3]; - __off64_t st_size; /* Size of file, in bytes. */ -# endif -# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif - __blksize_t st_blksize; /* Optimal block size for I/O. */ -# ifndef __USE_FILE_OFFSET64 - __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ -# else - long int st_pad4; - __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ -# endif - long int st_pad5[14]; -# endif /* __USE_TIME64_REDIRECTS */ - }; - -# ifdef __USE_LARGEFILE64 -struct stat64 - { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - unsigned long int st_dev; - long int st_pad1[3]; - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - unsigned long int st_rdev; /* Device number, if device. */ - long int st_pad2[3]; - __off64_t st_size; /* Size of file, in bytes. */ -# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif - __blksize_t st_blksize; /* Optimal block size for I/O. */ - long int st_pad3; - __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ - long int st_pad4[14]; -# endif /* __USE_TIME64_REDIRECTS */ - }; -# endif /* __USE_LARGEFILE64 */ - -#else /* _MIPS_SIM != _ABIO32 */ - -struct stat - { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - __dev_t st_dev; - int st_pad1[3]; /* Reserved for st_dev expansion */ -# ifndef __USE_FILE_OFFSET64 - __ino_t st_ino; -# else - __ino64_t st_ino; -# endif - __mode_t st_mode; - __nlink_t st_nlink; - __uid_t st_uid; - __gid_t st_gid; - __dev_t st_rdev; -# if !defined __USE_FILE_OFFSET64 - unsigned int st_pad2[2]; /* Reserved for st_rdev expansion */ - __off_t st_size; - int st_pad3; -# else - unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */ - __off64_t st_size; -# endif -# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif - __blksize_t st_blksize; - unsigned int st_pad4; -# ifndef __USE_FILE_OFFSET64 - __blkcnt_t st_blocks; -# else - __blkcnt64_t st_blocks; -# endif - int st_pad5[14]; +#include +#include + +#if defined __USE_FILE_OFFSET64 +# define __field64(type, type64, name) type64 name +#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T +# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T +# error "ino_t and off_t must both be the same type" # endif +# define __field64(type, type64, name) type name +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define __field64(type, type64, name) \ + type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad +#else +# define __field64(type, type64, name) \ + int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name +#endif + +struct stat + { + __dev_t st_dev; /* Device. */ + __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __dev_t __pad1; + __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ +#ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + int __glibc_reserved[2]; }; +#undef __field64 + #ifdef __USE_LARGEFILE64 struct stat64 { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - __dev_t st_dev; - unsigned int st_pad1[3]; /* Reserved for st_dev expansion */ - __ino64_t st_ino; - __mode_t st_mode; - __nlink_t st_nlink; - __uid_t st_uid; - __gid_t st_gid; - __dev_t st_rdev; - unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */ - __off64_t st_size; -# ifdef __USE_XOPEN2K8 + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __dev_t __pad1; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#ifdef __USE_XOPEN2K8 /* Nanosecond resolution timestamps are stored in a format equivalent to 'struct timespec'. This is the type used whenever possible but the Unix namespace rules do not allow the identifier 'timespec' to appear in the header. Therefore we have to handle the use of this header in strictly standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# else + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else __time_t st_atime; /* Time of last access. */ unsigned long int st_atimensec; /* Nscecs of last access. */ __time_t st_mtime; /* Time of last modification. */ unsigned long int st_mtimensec; /* Nsecs of last modification. */ __time_t st_ctime; /* Time of last status change. */ unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif - __blksize_t st_blksize; - unsigned int st_pad3; - __blkcnt64_t st_blocks; - int st_pad4[14]; -# endif /* __USE_TIME64_REDIRECTS */ -}; #endif - + int __glibc_reserved[2]; + }; #endif /* Tell code we have these members. */ #define _STATBUF_ST_BLKSIZE -#define _STATBUF_ST_RDEV +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC #endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/syscall.h b/lib/libc/include/generic-glibc/bits/syscall.h index 43e6645f7d238e0805be9874cadff3bfd5889520..147cc816809c06a7ab8a79cb858b50c9aa869f05 100644 --- a/lib/libc/include/generic-glibc/bits/syscall.h +++ b/lib/libc/include/generic-glibc/bits/syscall.h @@ -1,11 +1,11 @@ /* Generated at libc build time from syscall list. */ -/* The system call list corresponds to kernel 6.17. */ +/* The system call list corresponds to kernel 7.1. */ #ifndef _SYSCALL_H # error "Never use directly; include instead." #endif -#define __GLIBC_LINUX_VERSION_CODE 397568 +#define __GLIBC_LINUX_VERSION_CODE 459008 #ifdef __NR_FAST_atomic_update # define SYS_FAST_atomic_update __NR_FAST_atomic_update @@ -883,6 +883,10 @@ # define SYS_listmount __NR_listmount #endif +#ifdef __NR_listns +# define SYS_listns __NR_listns +#endif + #ifdef __NR_listxattr # define SYS_listxattr __NR_listxattr #endif @@ -1899,6 +1903,10 @@ # define SYS_rseq __NR_rseq #endif +#ifdef __NR_rseq_slice_yield +# define SYS_rseq_slice_yield __NR_rseq_slice_yield +#endif + #ifdef __NR_rt_sigaction # define SYS_rt_sigaction __NR_rt_sigaction #endif @@ -2551,6 +2559,10 @@ # define SYS_unshare __NR_unshare #endif +#ifdef __NR_uprobe +# define SYS_uprobe __NR_uprobe +#endif + #ifdef __NR_uretprobe # define SYS_uretprobe __NR_uretprobe #endif diff --git a/lib/libc/include/generic-glibc/bits/timesize.h b/lib/libc/include/generic-glibc/bits/timesize.h index 114eea77753240de1509241efac873c28a59e9d0..dff2da5ed6bf30ce6f5580aee352e0958d58b623 100644 --- a/lib/libc/include/generic-glibc/bits/timesize.h +++ b/lib/libc/include/generic-glibc/bits/timesize.h @@ -1,5 +1,5 @@ -/* Bit size of the time_t type at glibc build time, Linux/MIPS. - Copyright (C) 2021-2026 Free Software Foundation, Inc. +/* Bit size of the time_t type at glibc build time, general case. + Copyright (C) 2018-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,7 +16,5 @@ License along with the GNU C Library; if not, see . */ -#include - /* Size in bits of the 'time_t' type of the default ABI. */ -#define __TIMESIZE __WORDSIZE \ No newline at end of file +#define __TIMESIZE 64 \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/uio-ext.h b/lib/libc/include/generic-glibc/bits/uio-ext.h index e65cf77f433fcc0e7b4ce718f10c093fcc1d2097..1289a864c6d7432bada85113026c2a94b66a0251 100644 --- a/lib/libc/include/generic-glibc/bits/uio-ext.h +++ b/lib/libc/include/generic-glibc/bits/uio-ext.h @@ -51,6 +51,7 @@ extern ssize_t process_vm_writev (pid_t __pid, const struct iovec *__lvec, #define RWF_ATOMIC 0x00000040 /* Write is to be issued with torn-write prevention. */ #define RWF_DONTCACHE 0x00000080 /* Uncached buffered IO. */ +#define RWF_NOSIGNAL 0x00000100 /* Do not generate SIGPIPE on error. */ __END_DECLS diff --git a/lib/libc/include/generic-glibc/dlfcn.h b/lib/libc/include/generic-glibc/dlfcn.h index f12e3d68cd4e31c856a23e1c63bd5a2d6b597146..439f09dd9e3d8a5937343cc741a7778be646439b 100644 --- a/lib/libc/include/generic-glibc/dlfcn.h +++ b/lib/libc/include/generic-glibc/dlfcn.h @@ -167,7 +167,12 @@ enum the number of program headers in the array. */ RTLD_DI_PHDR = 11, - RTLD_DI_MAX = 11 + /* Treat ARG as `const char **' and at that location, store the address + of the directory name used to expand $ORIGIN in this shared object's + dependency file names. */ + RTLD_DI_ORIGIN_PATH = 12, + + RTLD_DI_MAX = 12 }; diff --git a/lib/libc/include/generic-glibc/elf.h b/lib/libc/include/generic-glibc/elf.h index a45dea41210184770afb26e837fb86f03d226b9a..ea2eca5e6dfbd1c0a63f9a90ddca67982061d64d 100644 --- a/lib/libc/include/generic-glibc/elf.h +++ b/lib/libc/include/generic-glibc/elf.h @@ -798,7 +798,8 @@ typedef struct #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ #define NT_X86_SHSTK 0x204 /* x86 SHSTK state */ #define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */ -#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ +#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves. This was + used in now removed s390-32 arch. */ #define NT_S390_TIMER 0x301 /* s390 timer register */ #define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ @@ -846,6 +847,7 @@ typedef struct #define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */ #define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged address control */ +#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */ #define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */ #define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers. */ @@ -3470,7 +3472,9 @@ enum /* Valid values for the e_flags field. */ -#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ +#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. + This was used in now removed s390-32 + arch. */ /* Additional s390 relocs */ diff --git a/lib/libc/include/generic-glibc/features.h b/lib/libc/include/generic-glibc/features.h index 5ef3af3beb712cf7cbb02d380cc68ef6f1b18d4d..a248a324911cb478b02d7f95cc87f8f9d6408327 100644 --- a/lib/libc/include/generic-glibc/features.h +++ b/lib/libc/include/generic-glibc/features.h @@ -162,7 +162,7 @@ #undef __GLIBC_USE_DEPRECATED_SCANF #undef __GLIBC_USE_C23_STRTOL -/* Suppress kernel-name space pollution unless user expressedly asks +/* Suppress kernel-name space pollution unless user explicitly asks for it. */ #ifndef _LOOSE_KERNEL_NAMES # define __KERNEL_STRICT_NAMES @@ -580,4 +580,4 @@ #include -#endif /* features.h */ +#endif /* features.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/fts.h b/lib/libc/include/generic-glibc/fts.h index 97d0f4a8a299fb9f4e439232fc9e33cd851b605e..d2164aa4ee5b51b2bc8b2f46df54614b941a4dbb 100644 --- a/lib/libc/include/generic-glibc/fts.h +++ b/lib/libc/include/generic-glibc/fts.h @@ -52,7 +52,29 @@ #include #include +#include +#include +#include +enum { __I_RING_SIZE = 4 }; + +/* When ir_empty is true, the ring is empty. + Otherwise, ir_data[B..F] are defined, where B..F is the contiguous + range of indices, modulo I_RING_SIZE, from back to front, inclusive. + Undefined elements of ir_data are always set to ir_default_val. + Popping from an empty ring aborts. + Pushing onto a full ring returns the displaced value. + An empty ring has F==B and ir_empty == true. + A ring with one entry still has F==B, but now ir_empty == false. */ +struct __I_ring +{ + int ir_data[__I_RING_SIZE]; + int ir_default_val; + unsigned int ir_front; + unsigned int ir_back; + bool ir_empty; +}; +typedef struct __I_ring __I_ring; typedef struct { struct _ftsent *fts_cur; /* current node */ @@ -73,11 +95,106 @@ typedef struct { #define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ #define FTS_XDEV 0x0040 /* don't cross devices */ #define FTS_WHITEOUT 0x0080 /* return whiteout information */ -#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ + + /* There are two ways to detect cycles. + The lazy way (which works only with FTS_PHYSICAL), + with which one may process a directory that is a + part of the cycle several times before detecting the cycle. + The "tight" way, whereby fts uses more memory (proportional + to number of "active" directories, aka distance from root + of current tree to current directory -- see active_dir_ht) + to detect any cycle right away. For example, du must use + this option to avoid counting disk space in a cycle multiple + times, but chown -R need not. + The default is to use the constant-memory lazy way, when possible + (see below). + + However, with FTS_LOGICAL (when following symlinks, e.g., chown -L) + using lazy cycle detection is inadequate. For example, traversing + a directory containing a symbolic link to a peer directory, it is + possible to encounter the same directory twice even though there + is no cycle: + dir + ... + slink -> dir + So, when FTS_LOGICAL is selected, we have to use a different + mode of cycle detection: FTS_TIGHT_CYCLE_CHECK. */ +#define FTS_TIGHT_CYCLE_CHECK 0x0400 + + /* Use this flag to enable semantics with which the parent + application may be made both more efficient and more robust. + Whereas the default is to visit each directory in a recursive + traversal (via chdir), using this flag makes it so the initial + working directory is never changed. Instead, these functions + perform the traversal via a virtual working directory, maintained + through the file descriptor member, fts_cwd_fd. */ +# define FTS_CWDFD 0x0800 + + /* Historically, for each directory that fts initially encounters, it would + open it, read all entries, and stat each entry, storing the results, and + then it would process the first entry. But that behavior is bad for + locality of reference, and also causes trouble with inode-simulating + file systems like FAT, CIFS, FUSE-based ones, etc., when entries from + their name/inode cache are flushed too early. + Use this flag to make fts_open and fts_read defer the stat/lstat/fststat + of each entry until it is actually processed. However, note that if you + use this option and also specify a comparison function, that function may + not examine any data via fts_statp. However, when fts_statp->st_mode is + nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data. + Of course, that happens only on file systems that provide useful + dirent.d_type data. */ +#define FTS_DEFER_STAT 0x1000 + + /* Use this flag to disable stripping of trailing slashes + from input path names during fts_open initialization. */ +#define FTS_VERBATIM 0x2000 + +#define FTS_MOUNT 0x4000 /* skip other devices */ +#define FTS_OPTIONMASK 0x7fff /* valid user option mask */ #define FTS_NAMEONLY 0x0100 /* (private) child names only */ #define FTS_STOP 0x0200 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ + + int fts_cwd_fd; /* the file descriptor on which the + virtual cwd is open, or AT_FDCWD */ + + /* Map a directory's device number to a boolean. The boolean is + true if for that file system (type determined by a single fstatfs + call per FS) st_nlink can be used to calculate the number of + sub-directory entries in a directory. + Using this table is an optimization that permits us to look up + file system type on a per-inode basis at the minimal cost of + calling fstatfs only once per traversed device. */ + struct hash_table *fts_leaf_optimization_works_ht; + + union { + /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is + specified. It records the directories between a starting + point and the current directory. I.e., a directory is + recorded here IFF we have visited it once, but we have not + yet completed processing of all its entries. Every time we + visit a new directory, we add that directory to this set. + When we finish with a directory (usually by visiting it a + second time), we remove it from this set. Each entry in + this data structure is a device/inode pair. This data + structure is used to detect directory cycles efficiently and + promptly even when the depth of a hierarchy is in the tens + of thousands. */ + struct hash_table *ht; + + /* FIXME: rename these two members to have the fts_ prefix */ + /* This data structure uses a lazy cycle-detection algorithm, + as done by rm via cycle-check.c. It's the default, + but it's not appropriate for programs like du. */ + struct cycle_check_state *state; + } fts_cycle; + + /* A stack of the file descriptors corresponding to the + most-recently traversed parent directories. + Currently used only in FTS_CWDFD mode. */ + __I_ring fts_fd_ring; } FTS; #ifdef __USE_LARGEFILE64 @@ -92,6 +209,13 @@ typedef struct { int fts_nitems; /* elements in the sort array */ int (*fts_compar) (const void *, const void *); /* compare fn */ int fts_options; /* fts_open options, global flags */ + int fts_cwd_fd; + struct hash_table *fts_leaf_optimization_works_ht; + union { + struct hash_table *ht; + struct cycle_check_state *state; + } fts_cycle; + __I_ring fts_fd_ring; } FTS64; #endif diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-32.h b/lib/libc/include/generic-glibc/gnu/lib-names-32.h index 77fbbc46100d7b2fcad49cb67f4af22df471f3a3..33f2700fb049c9de98b511c395753670af4df99b 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-32.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-32.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-hard.h b/lib/libc/include/generic-glibc/gnu/lib-names-hard.h index 393a0f91f49473362cb28026ea93f876f41da4c9..80f8b2e87ee57205b72076031c8e4711617647e2 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-hard.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-hard.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-n32_hard.h b/lib/libc/include/generic-glibc/gnu/lib-names-n32_hard.h index 2d2d46e4f5c3b76030cf34eb89a95f1debf40f27..09f068b64409436bd6e070b7f4642a596bb5907d 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-n32_hard.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-n32_hard.h @@ -23,4 +23,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-n64_hard.h b/lib/libc/include/generic-glibc/gnu/lib-names-n64_hard.h index 3d545313911cc42780f3f625b29e4b6078dd4c4e..caed888c6bd100ca1c0627bd0bdfba5146140775 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-n64_hard.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-n64_hard.h @@ -23,4 +23,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-o32_hard.h b/lib/libc/include/generic-glibc/gnu/lib-names-o32_hard.h index ab69cdcb7cfa958560ef796ba6f94a50398448dd..592d60dd33b5df50b16200332cf576666c2adf58 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-o32_hard.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-o32_hard.h @@ -23,4 +23,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-o32_soft.h b/lib/libc/include/generic-glibc/gnu/lib-names-o32_soft.h index 9be4d1e62012f6c7ce0ce5ed579989a65c795c7f..5ae29e9fb109b3f2bdfe275ae1a829769d66b0fb 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-o32_soft.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-o32_soft.h @@ -23,4 +23,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/lib-names-soft.h b/lib/libc/include/generic-glibc/gnu/lib-names-soft.h index c7a71323508f709975e8cb9f792dd2f928a275a3..fa665583dd54d5e8c17f2423181476fd94412be8 100644 --- a/lib/libc/include/generic-glibc/gnu/lib-names-soft.h +++ b/lib/libc/include/generic-glibc/gnu/lib-names-soft.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/netinet/in.h b/lib/libc/include/generic-glibc/netinet/in.h index 450338576f11be16bcf50d09d016d593f9ab5ca7..68b2016cdec8019a5e061dce477e6b1a69d3443e 100644 --- a/lib/libc/include/generic-glibc/netinet/in.h +++ b/lib/libc/include/generic-glibc/netinet/in.h @@ -91,6 +91,8 @@ enum #define IPPROTO_MPLS IPPROTO_MPLS IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */ #define IPPROTO_ETHERNET IPPROTO_ETHERNET + IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */ +#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG IPPROTO_RAW = 255, /* Raw IP packets. */ #define IPPROTO_RAW IPPROTO_RAW IPPROTO_SMC = 256, /* Shared Memory Communications. */ diff --git a/lib/libc/include/generic-glibc/netinet/tcp.h b/lib/libc/include/generic-glibc/netinet/tcp.h index 49764361e72d032438c000c278a16c8f77bbc555..ae66195fa6dc6b8181e6d4ad4092806a14295d33 100644 --- a/lib/libc/include/generic-glibc/netinet/tcp.h +++ b/lib/libc/include/generic-glibc/netinet/tcp.h @@ -80,6 +80,9 @@ as a cmsg on read. */ #define TCP_CM_INQ TCP_INQ #define TCP_TX_DELAY 37 /* Delay outgoing packets by XX usec. */ +#define TCP_RTO_MAX_MS 44 /* Max time to retransmit (msec). */ +#define TCP_RTO_MIN_US 45 /* Min time to retransmit (usec). */ +#define TCP_DELACK_MAX_US 46 /* Max delayed ack time (usec). */ #define TCP_REPAIR_ON 1 #define TCP_REPAIR_OFF 0 @@ -226,6 +229,24 @@ enum tcp_ca_state TCP_CA_Loss = 4 }; +/* Values for tcpi_ecn_mode after negotiation. */ +#define TCPI_ECN_MODE_DISABLED 0x0 +#define TCPI_ECN_MODE_RFC3168 0x1 +#define TCPI_ECN_MODE_ACCECN 0x2 +#define TCPI_ECN_MODE_PENDING 0x3 + +/* Values for tcpi_accecn_opt_seen. */ +#define TCP_ACCECN_OPT_NOT_SEEN 0x0 +#define TCP_ACCECN_OPT_EMPTY_SEEN 0x1 +#define TCP_ACCECN_OPT_COUNTER_SEEN 0x2 +#define TCP_ACCECN_OPT_FAIL_SEEN 0x3 + +/* Values for tcpi_accecn_fail_mode. */ +#define TCP_ACCECN_ACE_FAIL_SEND 0x1 +#define TCP_ACCECN_ACE_FAIL_RECV 0x2 +#define TCP_ACCECN_OPT_FAIL_SEND 0x4 +#define TCP_ACCECN_OPT_FAIL_RECV 0x8 + struct tcp_info { uint8_t tcpi_state; @@ -319,8 +340,10 @@ struct tcp_info uint32_t tcpi_received_e1_bytes; uint32_t tcpi_received_e0_bytes; uint32_t tcpi_received_ce_bytes; - uint16_t tcpi_accecn_fail_mode; - uint16_t tcpi_accecn_opt_seen; + uint32_t tcpi_ecn_mode:2, + tcpi_accecn_opt_seen:2, + tcpi_accecn_fail_mode:4, + tcpi_options2:24; }; /* Netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ diff --git a/lib/libc/include/generic-glibc/regex.h b/lib/libc/include/generic-glibc/regex.h index 29964af5b251c24a729a3326c173a0ae96455d96..5ff2fb611c92f20565163ee3430e43348665c37c 100644 --- a/lib/libc/include/generic-glibc/regex.h +++ b/lib/libc/include/generic-glibc/regex.h @@ -74,7 +74,7 @@ typedef unsigned long int reg_syntax_t; #ifdef __USE_GNU /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ -# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) +# define RE_BACKSLASH_ESCAPE_IN_LISTS 1ul /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. diff --git a/lib/libc/include/generic-glibc/spawn.h b/lib/libc/include/generic-glibc/spawn.h index b8e1eaee8f8c1432cb21fb069d2134573536827e..265a63ca28b30e0822fe9cf86e2214ec9de3cf3e 100644 --- a/lib/libc/include/generic-glibc/spawn.h +++ b/lib/libc/include/generic-glibc/spawn.h @@ -200,6 +200,26 @@ extern int posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t * int __fd, int __newfd) __THROW __nonnull ((1)); +#ifdef __USE_XOPEN2K24XSI + +/* Add an action changing the directory to PATH during spawn. This + affects the subsequent file actions. + Alias of posix_spawn_file_actions_addchdir_np. */ +extern int __REDIRECT_NTH (posix_spawn_file_actions_addchdir, + (posix_spawn_file_actions_t * __restrict __actions, + const char *__restrict __path), + posix_spawn_file_actions_addchdir_np); + +/* Add an action changing the directory to FD during spawn. This + affects the subsequent file actions. FD is not duplicated and must + be open when the file action is executed. + Alias of posix_spawn_file_actions_addfchdir_np. */ +extern int __REDIRECT_NTH (posix_spawn_file_actions_addfchdir, + (posix_spawn_file_actions_t *, int __fd), + posix_spawn_file_actions_addfchdir_np); + +#endif /* __USE_XOPEN2K24XSI */ + #ifdef __USE_MISC /* Add an action changing the directory to PATH during spawn. This affects the subsequent file actions. */ diff --git a/lib/libc/include/generic-glibc/stdlib.h b/lib/libc/include/generic-glibc/stdlib.h index 3ca2bb1f91bc38a0f6244c99113a3fb520f15b20..7d8d57f4cd907c77714fefe6615acf92624080cb 100644 --- a/lib/libc/include/generic-glibc/stdlib.h +++ b/lib/libc/include/generic-glibc/stdlib.h @@ -1225,4 +1225,4 @@ extern size_t memalignment (const void *__p); __END_DECLS -#endif /* stdlib.h */ +#endif /* stdlib.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/mount.h b/lib/libc/include/generic-glibc/sys/mount.h index bf226f5a738b6369caba0558d98357d3cb06e975..95834f8bf77e7fb2dbcb33fdb69ea81197335d5e 100644 --- a/lib/libc/include/generic-glibc/sys/mount.h +++ b/lib/libc/include/generic-glibc/sys/mount.h @@ -21,7 +21,6 @@ #ifndef _SYS_MOUNT_H #define _SYS_MOUNT_H 1 -#include #include #include #include @@ -190,6 +189,11 @@ enum /* fsmount flags. */ #define FSMOUNT_CLOEXEC 0x00000001 +// zig patch: check target glibc version +#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 +#define FSMOUNT_NAMESPACE 0x00000002 /* Create the mount in a new mount + namespace. */ +#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */ /* mount attributes used on fsmount. */ #define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only. */ @@ -267,10 +271,20 @@ enum fsconfig_command #define FSOPEN_CLOEXEC 0x00000001 /* open_tree flags. */ -#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ -#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ +#ifndef OPEN_TREE_CLONE +# define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ +#endif +#define OPEN_TREE_NAMESPACE (1 << 1) /* Clone the target tree into a new mount + namespace */ +#ifndef O_CLOEXEC +# include +# define O_CLOEXEC __O_CLOEXEC +#endif +#ifndef OPEN_TREE_CLOEXEC +# define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ +#endif -#endif +#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 36) || __GLIBC__ > 2 */ __BEGIN_DECLS diff --git a/lib/libc/include/generic-glibc/sys/pidfd.h b/lib/libc/include/generic-glibc/sys/pidfd.h index 3d9ab9430c72d2b947860d9fa6b9525a6ebc11aa..19ac5235e5868de39a7a0659b8da9d122467bb8f 100644 --- a/lib/libc/include/generic-glibc/sys/pidfd.h +++ b/lib/libc/include/generic-glibc/sys/pidfd.h @@ -64,6 +64,15 @@ #define PIDFD_INFO_EXIT (1UL << 3) /* Only returned if requested. */ #define PIDFD_INFO_COREDUMP (1UL << 4) +// zig patch: check target glibc version +#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 +/* Want/got supported mask flags */ +#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) +/* Always returned if PIDFD_INFO_COREDUMP is requested. */ +#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6) +/* Always returned if PIDFD_INFO_COREDUMP is requested. */ +#define PIDFD_INFO_COREDUMP_CODE (1UL << 7) +#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */ /* Value for coredump_mask in pidfd_info. Only valid if PIDFD_INFO_COREDUMP @@ -95,11 +104,28 @@ struct pidfd_info __uint32_t fsgid; __int32_t exit_code; __uint32_t coredump_mask; +// zig patch: check target glibc version +#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 + __uint32_t coredump_signal; + __uint32_t coredump_code; + __uint32_t coredump_pad; + __uint64_t supported_mask; +#else __uint32_t __spare1; +#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */ }; /* sizeof first published struct */ #define PIDFD_INFO_SIZE_VER0 64 +// zig patch: check target glibc version +#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 +/* sizeof second published struct */ +#define PIDFD_INFO_SIZE_VER1 72 +/* sizeof third published struct */ +#define PIDFD_INFO_SIZE_VER2 80 +/* sizeof fourth published struct */ +#define PIDFD_INFO_SIZE_VER3 88 +#endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */ #define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info) diff --git a/lib/libc/include/loongarch-linux-gnu/bits/hwcap.h b/lib/libc/include/loongarch-linux-gnu/bits/hwcap.h index d6335ffaa97c3c61cd1452cd3f01b8fc0903aa9d..72f26b63da5cbca1bac2ca0cbce6d3ff5f21c398 100644 --- a/lib/libc/include/loongarch-linux-gnu/bits/hwcap.h +++ b/lib/libc/include/loongarch-linux-gnu/bits/hwcap.h @@ -36,4 +36,6 @@ #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) #define HWCAP_LOONGARCH_PTW (1 << 13) -#define HWCAP_LOONGARCH_LSPW (1 << 14) \ No newline at end of file +#define HWCAP_LOONGARCH_LSPW (1 << 14) +#define HWCAP_LOONGARCH_SCQ (1 << 15) +#define HWCAP_LOONGARCH_LAM_BH (1 << 16) \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/bits/long-double.h b/lib/libc/include/loongarch-linux-gnu/bits/long-double.h deleted file mode 100644 index af7784dbe6dd85cd9538b5a7b437ab45de22eeb8..0000000000000000000000000000000000000000 --- a/lib/libc/include/loongarch-linux-gnu/bits/long-double.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Properties of long double type. ldbl-128 version. - Copyright (C) 2016-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* long double is distinct from double, so there is nothing to - define here. */ -#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0 \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/bits/struct_stat.h b/lib/libc/include/loongarch-linux-gnu/bits/struct_stat.h deleted file mode 100644 index 0462d37a6849812f485a6830a7c0dca303332636..0000000000000000000000000000000000000000 --- a/lib/libc/include/loongarch-linux-gnu/bits/struct_stat.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Definition for struct stat. - Copyright (C) 2020-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library. If not, see - . */ - -#if !defined _SYS_STAT_H && !defined _FCNTL_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_STRUCT_STAT_H -#define _BITS_STRUCT_STAT_H 1 - -#include -#include - -#if defined __USE_FILE_OFFSET64 -# define __field64(type, type64, name) type64 name -#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T -# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T -# error "ino_t and off_t must both be the same type" -# endif -# define __field64(type, type64, name) type name -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define __field64(type, type64, name) \ - type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad -#else -# define __field64(type, type64, name) \ - int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name -#endif - -struct stat - { - __dev_t st_dev; /* Device. */ - __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; - -#undef __field64 - -#ifdef __USE_LARGEFILE64 -struct stat64 - { - __dev_t st_dev; /* Device. */ - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __off64_t st_size; /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; -#endif - -/* Tell code we have these members. */ -#define _STATBUF_ST_BLKSIZE -#define _STATBUF_ST_RDEV -/* Nanosecond resolution time values are supported. */ -#define _STATBUF_ST_NSEC - -#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/bits/timesize.h b/lib/libc/include/loongarch-linux-gnu/bits/timesize.h deleted file mode 100644 index dff2da5ed6bf30ce6f5580aee352e0958d58b623..0000000000000000000000000000000000000000 --- a/lib/libc/include/loongarch-linux-gnu/bits/timesize.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Bit size of the time_t type at glibc build time, general case. - Copyright (C) 2018-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* Size in bits of the 'time_t' type of the default ABI. */ -#define __TIMESIZE 64 \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/bits/wordsize.h b/lib/libc/include/loongarch-linux-gnu/bits/wordsize.h index 5038df494751b3446f652bcb4d1c5d3e721a61ec..d4d561400b42e6e7004737b99bd8d82f6dc2a4f7 100644 --- a/lib/libc/include/loongarch-linux-gnu/bits/wordsize.h +++ b/lib/libc/include/loongarch-linux-gnu/bits/wordsize.h @@ -15,5 +15,16 @@ License along with the GNU C Library; if not, see . */ -#define __WORDSIZE 64 -#define __WORDSIZE_TIME64_COMPAT32 0 \ No newline at end of file +// zig patch: handle 32-bit and 64-bit in the same header +#if __loongarch_grlen == (__SIZEOF_POINTER__ * 8) +# define __WORDSIZE __loongarch_grlen +#else +# error unsupported ABI +#endif + +#define __WORDSIZE_TIME64_COMPAT32 0 + +#if __WORDSIZE == 32 +# define __WORDSIZE32_SIZE_ULONG 0 +# define __WORDSIZE32_PTRDIFF_LONG 0 +#endif diff --git a/lib/libc/include/loongarch-linux-gnu/fpu_control.h b/lib/libc/include/loongarch-linux-gnu/fpu_control.h index 69cd4213c79b5db9e6c6ec60dc454c8177c8ba6d..2a2354d760dcfaa389df58e0a942d4a679994387 100644 --- a/lib/libc/include/loongarch-linux-gnu/fpu_control.h +++ b/lib/libc/include/loongarch-linux-gnu/fpu_control.h @@ -94,6 +94,15 @@ extern void __loongarch_fpu_setcw (fpu_control_t) __THROW; #define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw)) #define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $fcsr0,%0" : : "r"(cw)) +#define _FPU_GET_ENABLES(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr1" : "=r"(cw)) +#define _FPU_SET_ENABLES(cw) __asm__ volatile ("movgr2fcsr $fcsr1,%0" : : "r"(cw)) + +#define _FPU_GET_FLAGS_CAUSE(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr2" : "=r"(cw)) +#define _FPU_SET_FLAGS_CAUSE(cw) __asm__ volatile ("movgr2fcsr $fcsr2,%0" : : "r"(cw)) + +#define _FPU_GET_RM(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr3" : "=r"(cw)) +#define _FPU_SET_RM(cw) __asm__ volatile ("movgr2fcsr $fcsr3,%0" : : "r"(cw)) + /* Default control word set at startup. */ extern fpu_control_t __fpu_control; diff --git a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-32.h b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32d.h similarity index 80% rename from lib/libc/include/powerpc-linux-gnu/gnu/lib-names-32.h rename to lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32d.h index af615a3d9f90d11fa61205c10ed15dbb63cb8985..f0780d70ef3f21f2e1cefa6f15f2bbc34c5ec651 100644 --- a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-32.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32d.h @@ -1,9 +1,10 @@ /* This file is automatically generated. */ #ifndef __GNU_LIB_NAMES_H -# error "Never use directly; include instead." +# error "Never use directly; include instead." #endif -#define LD_SO "ld.so.1" +#define LD_LINUX_LOONGARCH_ILP32D_SO "ld-linux-loongarch-ilp32d.so.1" +#define LD_SO "ld-linux-loongarch-ilp32d.so.1" #define LIBANL_SO "libanl.so.1" #define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" #define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" @@ -23,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v1.h b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32s.h similarity index 80% rename from lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v1.h rename to lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32s.h index 4b2c00bbd6ba2e0be21db7253984abfc9e0b8e35..012654c98f178fc1163e564175ccf9aee4521874 100644 --- a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v1.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-ilp32s.h @@ -1,10 +1,10 @@ /* This file is automatically generated. */ #ifndef __GNU_LIB_NAMES_H -# error "Never use directly; include instead." +# error "Never use directly; include instead." #endif -#define LD64_SO "ld64.so.1" -#define LD_SO "ld64.so.1" +#define LD_LINUX_LOONGARCH_ILP32S_SO "ld-linux-loongarch-ilp32s.so.1" +#define LD_SO "ld-linux-loongarch-ilp32s.so.1" #define LIBANL_SO "libanl.so.1" #define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" #define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64d.h b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64d.h index 8f030679c89545ea0ac048e744799051778f0b2c..000df5a7ec275335f903b9ce6a53861189deeca6 100644 --- a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64d.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64d.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64s.h b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64s.h index 7c8b796194b2f179d2dfddbd0a7040a76ba37aeb..0a812d367cac3923d148b019ece28f5698001930 100644 --- a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64s.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names-lp64s.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names.h b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names.h index c3eba41e095a1705b8478909b27017a74c8a7ff5..d7367183c2d250b519e7fc3018c51b7751930f2e 100644 --- a/lib/libc/include/loongarch-linux-gnu/gnu/lib-names.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/lib-names.h @@ -6,6 +6,12 @@ #include +#if __WORDSIZE == 32 && defined __loongarch_soft_float +# include +#endif +#if __WORDSIZE == 32 && defined __loongarch_double_float +# include +#endif #if __WORDSIZE == 64 && defined __loongarch_soft_float # include #endif diff --git a/lib/libc/include/powerpc-linux-gnu/gnu/stubs-64-v1.h b/lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32d.h similarity index 71% rename from lib/libc/include/powerpc-linux-gnu/gnu/stubs-64-v1.h rename to lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32d.h index 636dc73283f9e3508fca4713d7d911f47d284387..4c2911dd6d66a591544d5c76448086f5de7b36d5 100644 --- a/lib/libc/include/powerpc-linux-gnu/gnu/stubs-64-v1.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32d.h @@ -7,6 +7,11 @@ #error Applications may not define the macro _LIBC #endif +#define __stub___compat_bdflush +#define __stub___compat_create_module +#define __stub___compat_get_kernel_syms +#define __stub___compat_query_module +#define __stub___compat_uselib #define __stub_chflags #define __stub_fchflags #define __stub_gtty diff --git a/lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32s.h b/lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32s.h new file mode 100644 index 0000000000000000000000000000000000000000..6ce02418e69609f4642a522910708769e96d6ee9 --- /dev/null +++ b/lib/libc/include/loongarch-linux-gnu/gnu/stubs-ilp32s.h @@ -0,0 +1,38 @@ +/* This file is automatically generated. + It defines a symbol `__stub_FUNCTION' for each function + in the C library which is a stub, meaning it will fail + every time called, usually setting errno to ENOSYS. */ + +#ifdef _LIBC + #error Applications may not define the macro _LIBC +#endif + +#define __stub___compat_bdflush +#define __stub___compat_create_module +#define __stub___compat_get_kernel_syms +#define __stub___compat_query_module +#define __stub___compat_uselib +#define __stub_chflags +#define __stub_fchflags +#define __stub_feclearexcept +#define __stub_fedisableexcept +#define __stub_feenableexcept +#define __stub_fegetenv +#define __stub_fegetexcept +#define __stub_fegetexceptflag +#define __stub_fegetmode +#define __stub_fegetround +#define __stub_feholdexcept +#define __stub_feraiseexcept +#define __stub_fesetenv +#define __stub_fesetexcept +#define __stub_fesetexceptflag +#define __stub_fesetmode +#define __stub_fesetround +#define __stub_fetestexcept +#define __stub_feupdateenv +#define __stub_gtty +#define __stub_revoke +#define __stub_setlogin +#define __stub_sigreturn +#define __stub_stty \ No newline at end of file diff --git a/lib/libc/include/loongarch-linux-gnu/gnu/stubs.h b/lib/libc/include/loongarch-linux-gnu/gnu/stubs.h index ea3f10c4213c01ccc0c0dd0fd9aef9b114ddf0cd..694ca60a5bfeabaa4e0ea8b594839408d21be11d 100644 --- a/lib/libc/include/loongarch-linux-gnu/gnu/stubs.h +++ b/lib/libc/include/loongarch-linux-gnu/gnu/stubs.h @@ -4,6 +4,12 @@ #include +#if __WORDSIZE == 32 && defined __loongarch_soft_float +# include +#endif +#if __WORDSIZE == 32 && defined __loongarch_double_float +# include +#endif #if __WORDSIZE == 64 && defined __loongarch_soft_float # include #endif diff --git a/lib/libc/include/loongarch-linux-gnu/sys/asm.h b/lib/libc/include/loongarch-linux-gnu/sys/asm.h index 973feb6effa26ea10d6b1af85ce2784a32ec8135..17465154a3ebe02d36cdf4b013c23acad75a58d4 100644 --- a/lib/libc/include/loongarch-linux-gnu/sys/asm.h +++ b/lib/libc/include/loongarch-linux-gnu/sys/asm.h @@ -23,10 +23,8 @@ #include /* Macros to handle different pointer/register sizes for 32/64-bit code. */ +#if __loongarch_grlen == 64 #define SZREG 8 -#define SZFREG 8 -#define SZVREG 16 -#define SZXREG 32 #define REG_L ld.d #define REG_S st.d #define SRLI srli.d @@ -34,10 +32,38 @@ #define ADDI addi.d #define ADD add.d #define SUB sub.d -#define BSTRINS bstrins.d #define LI li.d -#define FREG_L fld.d -#define FREG_S fst.d +#define BSTRINS bstrins.d + +#elif __loongarch_grlen == 32 + +#define SZREG 4 +#define REG_L ld.w +#define REG_S st.w +#define SRLI srli.w +#define SLLI slli.w +#define ADDI addi.w +#define ADD add.w +#define SUB sub.w +#define LI li.w +#define BSTRINS bstrins.w + +#else +#error __loongarch_grlen must equal 32 or 64 +#endif + +#if __loongarch_frlen == 64 + #define SZFREG 8 + #define FREG_L fld.d + #define FREG_S fst.d +#elif __loongarch_frlen == 32 + #define SZFREG 4 + #define FREG_L fld.s + #define FREG_S fst.s +#endif + +#define SZVREG 16 +#define SZXREG 32 /* Declare leaf routine. The usage of macro LEAF/ENTRY is as follows: diff --git a/lib/libc/include/m68k-linux-gnu/gnu/lib-names.h b/lib/libc/include/m68k-linux-gnu/gnu/lib-names.h index f72e37a69b31d263771248ddb6141300af975b2e..82aba9b01dc90b844da3f9efb076aa950cc5e348 100644 --- a/lib/libc/include/m68k-linux-gnu/gnu/lib-names.h +++ b/lib/libc/include/m68k-linux-gnu/gnu/lib-names.h @@ -24,6 +24,7 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" #endif /* gnu/lib-names.h */ \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/bits/long-double.h b/lib/libc/include/mips-linux-gnu/bits/long-double.h similarity index 82% rename from lib/libc/include/aarch64-linux-gnu/bits/long-double.h rename to lib/libc/include/mips-linux-gnu/bits/long-double.h index af7784dbe6dd85cd9538b5a7b437ab45de22eeb8..ebf6ac878fbf42241d0b2bcaf8c6049d08d827c5 100644 --- a/lib/libc/include/aarch64-linux-gnu/bits/long-double.h +++ b/lib/libc/include/mips-linux-gnu/bits/long-double.h @@ -1,4 +1,4 @@ -/* Properties of long double type. ldbl-128 version. +/* Properties of long double type. MIPS version. Copyright (C) 2016-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,6 +16,9 @@ License along with the GNU C Library; if not, see . */ -/* long double is distinct from double, so there is nothing to - define here. */ +#include + +#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32 +# define __NO_LONG_DOUBLE_MATH 1 +#endif #define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0 \ No newline at end of file diff --git a/lib/libc/include/mips-linux-gnu/bits/struct_stat.h b/lib/libc/include/mips-linux-gnu/bits/struct_stat.h new file mode 100644 index 0000000000000000000000000000000000000000..231c875e7ab2c703e50746e2191ddc411c0878a2 --- /dev/null +++ b/lib/libc/include/mips-linux-gnu/bits/struct_stat.h @@ -0,0 +1,237 @@ +/* Definition for struct stat. + Copyright (C) 2020-2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#if !defined _SYS_STAT_H && !defined _FCNTL_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_STRUCT_STAT_H +#define _BITS_STRUCT_STAT_H 1 + +#include + +#if _MIPS_SIM == _ABIO32 +/* Structure describing file characteristics. */ +struct stat + { +# ifdef __USE_TIME64_REDIRECTS +# include +# else + unsigned long int st_dev; + long int st_pad1[3]; +# ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +# else + __ino64_t st_ino; /* File serial number. */ +# endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned long int st_rdev; /* Device number, if device. */ +# ifndef __USE_FILE_OFFSET64 + long int st_pad2[2]; + __off_t st_size; /* Size of file, in bytes. */ + /* SVR4 added this extra long to allow for expansion of off_t. */ + long int st_pad3; +# else + long int st_pad2[3]; + __off64_t st_size; /* Size of file, in bytes. */ +# endif +# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ +# else + long int st_pad4; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ +# endif + long int st_pad5[14]; +# endif /* __USE_TIME64_REDIRECTS */ + }; + +# ifdef __USE_LARGEFILE64 +struct stat64 + { +# ifdef __USE_TIME64_REDIRECTS +# include +# else + unsigned long int st_dev; + long int st_pad1[3]; + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned long int st_rdev; /* Device number, if device. */ + long int st_pad2[3]; + __off64_t st_size; /* Size of file, in bytes. */ +# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + long int st_pad3; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ + long int st_pad4[14]; +# endif /* __USE_TIME64_REDIRECTS */ + }; +# endif /* __USE_LARGEFILE64 */ + +#else /* _MIPS_SIM != _ABIO32 */ + +struct stat + { +# ifdef __USE_TIME64_REDIRECTS +# include +# else + __dev_t st_dev; + int st_pad1[3]; /* Reserved for st_dev expansion */ +# ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; +# else + __ino64_t st_ino; +# endif + __mode_t st_mode; + __nlink_t st_nlink; + __uid_t st_uid; + __gid_t st_gid; + __dev_t st_rdev; +# if !defined __USE_FILE_OFFSET64 + unsigned int st_pad2[2]; /* Reserved for st_rdev expansion */ + __off_t st_size; + int st_pad3; +# else + unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */ + __off64_t st_size; +# endif +# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +# endif + __blksize_t st_blksize; + unsigned int st_pad4; +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; +# else + __blkcnt64_t st_blocks; +# endif + int st_pad5[14]; +# endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { +# ifdef __USE_TIME64_REDIRECTS +# include +# else + __dev_t st_dev; + unsigned int st_pad1[3]; /* Reserved for st_dev expansion */ + __ino64_t st_ino; + __mode_t st_mode; + __nlink_t st_nlink; + __uid_t st_uid; + __gid_t st_gid; + __dev_t st_rdev; + unsigned int st_pad2[3]; /* Reserved for st_rdev expansion */ + __off64_t st_size; +# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +# endif + __blksize_t st_blksize; + unsigned int st_pad3; + __blkcnt64_t st_blocks; + int st_pad4[14]; +# endif /* __USE_TIME64_REDIRECTS */ +}; +#endif + +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/timesize.h b/lib/libc/include/mips-linux-gnu/bits/timesize.h similarity index 93% rename from lib/libc/include/s390x-linux-gnu/bits/timesize.h rename to lib/libc/include/mips-linux-gnu/bits/timesize.h index 5c231fe380193665c3e791dc1c16ef284787d758..114eea77753240de1509241efac873c28a59e9d0 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/timesize.h +++ b/lib/libc/include/mips-linux-gnu/bits/timesize.h @@ -1,4 +1,4 @@ -/* Bit size of the time_t type at glibc build time, Linux/s390. +/* Bit size of the time_t type at glibc build time, Linux/MIPS. Copyright (C) 2021-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/lib/libc/include/mips-linux-gnu/bits/waitstatus.h b/lib/libc/include/mips-linux-gnu/bits/waitstatus.h new file mode 100644 index 0000000000000000000000000000000000000000..1b7a5a3195a98951a56088ee2e3d7b48874dd835 --- /dev/null +++ b/lib/libc/include/mips-linux-gnu/bits/waitstatus.h @@ -0,0 +1,68 @@ +/* Definitions of status bits for `wait' et al. + MIPS version, based on the generic version (bits/waitstatus.h). + + Copyright (C) 1992-2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#if !defined _SYS_WAIT_H && !defined _STDLIB_H +# error "Never include directly; use instead." +#endif + + +/* On MIPS SIGRTMAX is 127, so we need to handle the status code 127 + which is impossible on other ports. */ + +/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ +#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) + +/* If WIFSIGNALED(STATUS), the terminating signal. */ +#define __WTERMSIG(status) ((status) & 0x7f) + +/* If WIFSTOPPED(STATUS), the signal that stopped the child. */ +#define __WSTOPSIG(status) __WEXITSTATUS(status) + +/* Nonzero if STATUS indicates normal termination. */ +#define __WIFEXITED(status) (__WTERMSIG(status) == 0) + +/* Nonzero if STATUS indicates termination by a signal. */ +static __inline int +__WIFSIGNALED (int __status) +{ + return ((signed char) ((__status & 0x7f) + 1) >> 1) > 0 || __status == 0x7f; +} + +/* Nonzero if STATUS indicates the child is stopped. */ +static __inline int +__WIFSTOPPED (int __status) +{ + return (__status & 0xff) == 0x7f && __status != 0x7f; +} + +/* Nonzero if STATUS indicates the child continued after a stop. We only + define this if provides the WCONTINUED flag bit. */ +#ifdef WCONTINUED +# define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif + +/* Nonzero if STATUS indicates the child dumped core. */ +#define __WCOREDUMP(status) ((status) & __WCOREFLAG) + +/* Macros for constructing status values. */ +#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +#define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#define __W_CONTINUED 0xffff +#define __WCOREFLAG 0x80 \ No newline at end of file diff --git a/lib/libc/include/powerpc-linux-gnu/bits/long-double.h b/lib/libc/include/powerpc-linux-gnu/bits/long-double.h index 6c9cf2949f916b13700552fd7c1fe852fa507460..e20cbda37abca98ee6597594ff6264ae7ed8f3a7 100644 --- a/lib/libc/include/powerpc-linux-gnu/bits/long-double.h +++ b/lib/libc/include/powerpc-linux-gnu/bits/long-double.h @@ -1,5 +1,5 @@ /* Properties of long double type. ldbl-opt version. - Copyright (C) 2016-2026 Free Software Foundation, Inc. + Copyright (C) 2019-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/lib/libc/include/generic-glibc/bits/ppc.h b/lib/libc/include/powerpc-linux-gnu/bits/ppc.h similarity index 100% rename from lib/libc/include/generic-glibc/bits/ppc.h rename to lib/libc/include/powerpc-linux-gnu/bits/ppc.h diff --git a/lib/libc/include/powerpc-linux-gnu/bits/struct_mutex.h b/lib/libc/include/powerpc-linux-gnu/bits/struct_mutex.h index ebf2d50922ee0114298519286785f965771985d9..95fc7f4cc7e18960cc0aa678b866c18b3a03e9be 100644 --- a/lib/libc/include/powerpc-linux-gnu/bits/struct_mutex.h +++ b/lib/libc/include/powerpc-linux-gnu/bits/struct_mutex.h @@ -59,4 +59,4 @@ struct __pthread_mutex_s 0, 0, 0, __kind, 0, { { 0, 0 } } #endif -#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h b/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h index 36329b69d756c708f60be53d92609a7175acef8a..0041d62398223239ae58d9bc47f4b552610cedeb 100644 --- a/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h +++ b/lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/platform/ppc.h b/lib/libc/include/powerpc-linux-gnu/sys/platform/ppc.h similarity index 100% rename from lib/libc/include/generic-glibc/sys/platform/ppc.h rename to lib/libc/include/powerpc-linux-gnu/sys/platform/ppc.h diff --git a/lib/libc/include/riscv-linux-gnu/bits/long-double.h b/lib/libc/include/riscv-linux-gnu/bits/long-double.h deleted file mode 100644 index af7784dbe6dd85cd9538b5a7b437ab45de22eeb8..0000000000000000000000000000000000000000 --- a/lib/libc/include/riscv-linux-gnu/bits/long-double.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Properties of long double type. ldbl-128 version. - Copyright (C) 2016-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* long double is distinct from double, so there is nothing to - define here. */ -#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0 \ No newline at end of file diff --git a/lib/libc/include/riscv-linux-gnu/bits/struct_stat.h b/lib/libc/include/riscv-linux-gnu/bits/struct_stat.h deleted file mode 100644 index 0462d37a6849812f485a6830a7c0dca303332636..0000000000000000000000000000000000000000 --- a/lib/libc/include/riscv-linux-gnu/bits/struct_stat.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Definition for struct stat. - Copyright (C) 2020-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library. If not, see - . */ - -#if !defined _SYS_STAT_H && !defined _FCNTL_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_STRUCT_STAT_H -#define _BITS_STRUCT_STAT_H 1 - -#include -#include - -#if defined __USE_FILE_OFFSET64 -# define __field64(type, type64, name) type64 name -#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T -# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T -# error "ino_t and off_t must both be the same type" -# endif -# define __field64(type, type64, name) type name -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define __field64(type, type64, name) \ - type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad -#else -# define __field64(type, type64, name) \ - int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name -#endif - -struct stat - { - __dev_t st_dev; /* Device. */ - __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; - -#undef __field64 - -#ifdef __USE_LARGEFILE64 -struct stat64 - { - __dev_t st_dev; /* Device. */ - __ino64_t st_ino; /* File serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - __dev_t __pad1; - __off64_t st_size; /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - int __pad2; - __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ -#ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -#else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -#endif - int __glibc_reserved[2]; - }; -#endif - -/* Tell code we have these members. */ -#define _STATBUF_ST_BLKSIZE -#define _STATBUF_ST_RDEV -/* Nanosecond resolution time values are supported. */ -#define _STATBUF_ST_NSEC - -#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/lib/libc/include/riscv-linux-gnu/bits/timesize.h b/lib/libc/include/riscv-linux-gnu/bits/timesize.h deleted file mode 100644 index dff2da5ed6bf30ce6f5580aee352e0958d58b623..0000000000000000000000000000000000000000 --- a/lib/libc/include/riscv-linux-gnu/bits/timesize.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Bit size of the time_t type at glibc build time, general case. - Copyright (C) 2018-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* Size in bits of the 'time_t' type of the default ABI. */ -#define __TIMESIZE 64 \ No newline at end of file diff --git a/lib/libc/include/riscv-linux-gnu/gnu/lib-names-ilp32d.h b/lib/libc/include/riscv-linux-gnu/gnu/lib-names-ilp32d.h index 33fd7061de58a4aeca1c876789202fc51a5be641..37e0c85dd4ea29bcca29f0b710981b74e5e8e3bc 100644 --- a/lib/libc/include/riscv-linux-gnu/gnu/lib-names-ilp32d.h +++ b/lib/libc/include/riscv-linux-gnu/gnu/lib-names-ilp32d.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/riscv-linux-gnu/gnu/lib-names-lp64d.h b/lib/libc/include/riscv-linux-gnu/gnu/lib-names-lp64d.h index 0b66bda6d611e45af8ebfbaa34b5569ae01e0c87..8117af98ffff4eec5296b1d16e390402785df0d8 100644 --- a/lib/libc/include/riscv-linux-gnu/gnu/lib-names-lp64d.h +++ b/lib/libc/include/riscv-linux-gnu/gnu/lib-names-lp64d.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/elfclass.h b/lib/libc/include/s390x-linux-gnu/bits/elfclass.h index 325ca0fe4b41d0af0242fb38611aca0b39d4b525..1082cffe057afa53e293fe6aec0c117aab32723d 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/elfclass.h +++ b/lib/libc/include/s390x-linux-gnu/bits/elfclass.h @@ -27,11 +27,6 @@ #define __ELF_NATIVE_CLASS __WORDSIZE -#if __WORDSIZE == 64 /* 64 bit Linux for S/390 is exceptional as it has .hash section with 64 bit entries. */ -typedef uint64_t Elf_Symndx; -#else -/* 32 bit Linux for S/390 has normal .hash section entries with 32 bits. */ -typedef uint32_t Elf_Symndx; -#endif \ No newline at end of file +typedef uint64_t Elf_Symndx; \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/environments.h b/lib/libc/include/s390x-linux-gnu/bits/environments.h deleted file mode 100644 index 6a5d3e997c9e6592b4c5077da6e5f1d9e40d9b40..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/bits/environments.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 1999-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _UNISTD_H -# error "Never include this file directly. Use instead" -#endif - -#include - -/* This header should define the following symbols under the described - situations. A value `1' means that the model is always supported, - `-1' means it is never supported. Undefined means it cannot be - statically decided. - - _POSIX_V7_ILP32_OFF32 32bit int, long, pointers, and off_t type - _POSIX_V7_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type - - _POSIX_V7_LP64_OFF32 64bit long and pointers and 32bit off_t type - _POSIX_V7_LPBIG_OFFBIG 64bit long and pointers and large off_t type - - The macros _POSIX_V6_ILP32_OFF32, _POSIX_V6_ILP32_OFFBIG, - _POSIX_V6_LP64_OFF32, _POSIX_V6_LPBIG_OFFBIG, _XBS5_ILP32_OFF32, - _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and _XBS5_LPBIG_OFFBIG were - used in previous versions of the Unix standard and are available - only for compatibility. -*/ - -#if __WORDSIZE == 64 - -/* Environments with 32-bit wide pointers are optionally provided. - Therefore following macros aren't defined: - # undef _POSIX_V7_ILP32_OFF32 - # undef _POSIX_V7_ILP32_OFFBIG - # undef _POSIX_V6_ILP32_OFF32 - # undef _POSIX_V6_ILP32_OFFBIG - # undef _XBS5_ILP32_OFF32 - # undef _XBS5_ILP32_OFFBIG - and users need to check at runtime. */ - -/* We also have no use (for now) for an environment with bigger pointers - and offsets. */ -# define _POSIX_V7_LPBIG_OFFBIG -1 -# define _POSIX_V6_LPBIG_OFFBIG -1 -# define _XBS5_LPBIG_OFFBIG -1 - -/* By default we have 64-bit wide `long int', pointers and `off_t'. */ -# define _POSIX_V7_LP64_OFF64 1 -# define _POSIX_V6_LP64_OFF64 1 -# define _XBS5_LP64_OFF64 1 - -#else /* __WORDSIZE == 32 */ - -/* By default we have 32-bit wide `int', `long int', pointers and `off_t' - and all platforms support LFS. */ -# define _POSIX_V7_ILP32_OFF32 1 -# define _POSIX_V7_ILP32_OFFBIG 1 -# define _POSIX_V6_ILP32_OFF32 1 -# define _POSIX_V6_ILP32_OFFBIG 1 -# define _XBS5_ILP32_OFF32 1 -# define _XBS5_ILP32_OFFBIG 1 - -/* We optionally provide an environment with the above size but an 64-bit - side `off_t'. Therefore we don't define _POSIX_V7_ILP32_OFFBIG. */ - -/* Environments with 64-bit wide pointers can be provided, - so these macros aren't defined: - # undef _POSIX_V7_LP64_OFF64 - # undef _POSIX_V7_LPBIG_OFFBIG - # undef _POSIX_V6_LP64_OFF64 - # undef _POSIX_V6_LPBIG_OFFBIG - # undef _XBS5_LP64_OFF64 - # undef _XBS5_LPBIG_OFFBIG - and sysconf tests for it at runtime. */ - -#endif /* __WORDSIZE == 32 */ - -#define __ILP32_OFF32_CFLAGS "-m31" -#define __ILP32_OFFBIG_CFLAGS "-m31 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" -#define __ILP32_OFF32_LDFLAGS "-m31" -#define __ILP32_OFFBIG_LDFLAGS "-m31" -#define __LP64_OFF64_CFLAGS "-m64" -#define __LP64_OFF64_LDFLAGS "-m64" \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/fcntl.h b/lib/libc/include/s390x-linux-gnu/bits/fcntl.h index 1d209c616c834cb7d1e8c4220a68852418694265..65df93eaf1e48e53690ec83f9cf4c1f17b3c6026 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/fcntl.h +++ b/lib/libc/include/s390x-linux-gnu/bits/fcntl.h @@ -22,29 +22,20 @@ #include -#if __WORDSIZE == 64 /* Not necessary, files are always with 64bit off_t. */ -# define __O_LARGEFILE 0 -#endif +#define __O_LARGEFILE 0 -#if __WORDSIZE == 64 /* Not necessary, we always have 64-bit offsets. */ -# define F_GETLK64 5 /* Get record locking info. */ -# define F_SETLK64 6 /* Set record locking info (non-blocking). */ -# define F_SETLKW64 7 /* Set record locking info (blocking). */ -#endif +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ struct flock { short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ -#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 __off_t l_start; /* Offset where the lock begins. */ __off_t l_len; /* Size of the locked area; zero means until EOF. */ -#else - __off64_t l_start; /* Offset where the lock begins. */ - __off64_t l_len; /* Size of the locked area; zero means until EOF. */ -#endif __pid_t l_pid; /* Process holding the lock. */ }; @@ -59,13 +50,8 @@ struct flock64 }; #endif -#if __WORDSIZE == 64 -# define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */ -# define __POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */ -#else -# define __POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ -# define __POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ -#endif +#define __POSIX_FADV_DONTNEED 6 /* Don't need these pages. */ +#define __POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */ /* Include generic Linux declarations. */ #include \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/fenv.h b/lib/libc/include/s390x-linux-gnu/bits/fenv.h index 6fb9372043231b6e4303457c2b102b56fc39e728..e53e9e1d9ab8b9b5ff63b5f3c6f959ad2253b6ed 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/fenv.h +++ b/lib/libc/include/s390x-linux-gnu/bits/fenv.h @@ -77,9 +77,9 @@ typedef struct { fexcept_t __fpc; void *__glibc_reserved; - /* The field __unused (formerly __ieee_instruction_pointer) is a relict from - commit "Remove PTRACE_PEEKUSER" (87b9b50f0d4b92248905e95a06a13c513dc45e59) - and isn't used anymore. */ + /* The field __glibc_reserved (formerly __ieee_instruction_pointer) is a + relict from commit "Remove PTRACE_PEEKUSER" + (87b9b50f0d4b92248905e95a06a13c513dc45e59) and isn't used anymore. */ } fenv_t; /* If the default argument is used we use this value. */ @@ -96,4 +96,4 @@ typedef unsigned int femode_t; /* Default floating-point control modes. */ # define FE_DFL_MODE ((const femode_t *) -1L) -#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/link.h b/lib/libc/include/s390x-linux-gnu/bits/link.h index 96694b37a417838cb4452446e0217fd7e3d4ebed..9eeb39b381bc9292c9b5c3842c296aa9db0b74b7 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/link.h +++ b/lib/libc/include/s390x-linux-gnu/bits/link.h @@ -23,64 +23,6 @@ typedef char La_s390_vr[16]; #endif -#if __ELF_NATIVE_CLASS == 32 - -/* Registers for entry into PLT on s390-32. */ -typedef struct La_s390_32_regs -{ - uint32_t lr_r2; - uint32_t lr_r3; - uint32_t lr_r4; - uint32_t lr_r5; - uint32_t lr_r6; - double lr_fp0; - double lr_fp2; -# if defined HAVE_S390_VX_ASM_SUPPORT - La_s390_vr lr_v24; - La_s390_vr lr_v25; - La_s390_vr lr_v26; - La_s390_vr lr_v27; - La_s390_vr lr_v28; - La_s390_vr lr_v29; - La_s390_vr lr_v30; - La_s390_vr lr_v31; -# endif -} La_s390_32_regs; - -/* Return values for calls from PLT on s390-32. */ -typedef struct La_s390_32_retval -{ - uint32_t lrv_r2; - uint32_t lrv_r3; - double lrv_fp0; -# if defined HAVE_S390_VX_ASM_SUPPORT - La_s390_vr lrv_v24; -# endif -} La_s390_32_retval; - - -__BEGIN_DECLS - -extern Elf32_Addr la_s390_32_gnu_pltenter (Elf32_Sym *__sym, - unsigned int __ndx, - uintptr_t *__refcook, - uintptr_t *__defcook, - La_s390_32_regs *__regs, - unsigned int *__flags, - const char *__symname, - long int *__framesizep); -extern unsigned int la_s390_32_gnu_pltexit (Elf32_Sym *__sym, - unsigned int __ndx, - uintptr_t *__refcook, - uintptr_t *__defcook, - const La_s390_32_regs *__inregs, - La_s390_32_retval *__outregs, - const char *symname); - -__END_DECLS - -#else - /* Registers for entry into PLT on s390-64. */ typedef struct La_s390_64_regs { @@ -134,6 +76,4 @@ extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym, La_s390_64_retval *__outregs, const char *__symname); -__END_DECLS - -#endif \ No newline at end of file +__END_DECLS \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/procfs-extra.h b/lib/libc/include/s390x-linux-gnu/bits/procfs-extra.h deleted file mode 100644 index 7fb00d4146dae8fca24958e976e831c961090952..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/bits/procfs-extra.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Extra sys/procfs.h definitions. S/390 version. - Copyright (C) 2000-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_PROCFS_H -# error "Never include directly; use instead." -#endif - -#if __WORDSIZE == 64 - -/* Provide 32-bit variants so that BFD can read 32-bit - core files. */ -#define ELF_NGREG32 36 -typedef unsigned int elf_greg_t32; -typedef elf_greg_t32 - elf_gregset_t32[ELF_NGREG32] __attribute__ ((__aligned__ (8))); -typedef elf_fpregset_t elf_fpregset_t32; - -struct elf_prstatus32 - { - struct elf_siginfo pr_info; /* Info associated with signal. */ - short int pr_cursig; /* Current signal. */ - unsigned int pr_sigpend; /* Set of pending signals. */ - unsigned int pr_sighold; /* Set of held signals. */ - __pid_t pr_pid; - __pid_t pr_ppid; - __pid_t pr_pgrp; - __pid_t pr_sid; - struct - { - int tv_sec, tv_usec; - } pr_utime, /* User time. */ - pr_stime, /* System time. */ - pr_cutime, /* Cumulative user time. */ - pr_cstime; /* Cumulative system time. */ - elf_gregset_t32 pr_reg; /* GP registers. */ - int pr_fpvalid; /* True if math copro being used. */ - }; - -struct elf_prpsinfo32 - { - char pr_state; /* Numeric process state. */ - char pr_sname; /* Char for pr_state. */ - char pr_zomb; /* Zombie. */ - char pr_nice; /* Nice val. */ - unsigned int pr_flag; /* Flags. */ - unsigned short int pr_uid; - unsigned short int pr_gid; - int pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* Filename of executable. */ - char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ - }; - -typedef elf_gregset_t32 prgregset32_t; -typedef elf_fpregset_t32 prfpregset32_t; - -typedef struct elf_prstatus32 prstatus32_t; -typedef struct elf_prpsinfo32 prpsinfo32_t; - -#endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/procfs-id.h b/lib/libc/include/s390x-linux-gnu/bits/procfs-id.h deleted file mode 100644 index 9e8570cfe612efd5d35867d0a70a20593fde16f9..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/bits/procfs-id.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Types of pr_uid and pr_gid in struct elf_prpsinfo. S/390 version. - Copyright (C) 2018-2026 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_PROCFS_H -# error "Never include directly; use instead." -#endif - -#if __WORDSIZE == 64 -typedef unsigned int __pr_uid_t; -typedef unsigned int __pr_gid_t; -#else -typedef unsigned short int __pr_uid_t; -typedef unsigned short int __pr_gid_t; -#endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/setjmp.h b/lib/libc/include/s390x-linux-gnu/bits/setjmp.h index 7d660921ab0295c49a77d9fb12cf4b021546d8c3..451857ec455a20350777d9bd21ed38353e7c4763 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/setjmp.h +++ b/lib/libc/include/s390x-linux-gnu/bits/setjmp.h @@ -33,13 +33,7 @@ typedef struct __s390_jmp_buf /* We save registers 6-15. */ long int __gregs[10]; -# if __WORDSIZE == 64 - /* We save fpu registers f8 - f15. */ long __fpregs[8]; -# else - /* We save fpu registers 4 and 6. */ - long __fpregs[4]; -# endif } __jmp_buf[1]; #endif diff --git a/lib/libc/include/s390x-linux-gnu/bits/sigaction.h b/lib/libc/include/s390x-linux-gnu/bits/sigaction.h index 44883efbe768731d6953e626f57588887505c712..7012eab006a3e4b42515fb7fc8c7d0c026c1dc98 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/sigaction.h +++ b/lib/libc/include/s390x-linux-gnu/bits/sigaction.h @@ -1,4 +1,4 @@ -/* Definitions for 31 & 64 bit S/390 sigaction. +/* Definitions for 64 bit S/390 sigaction. Copyright (C) 2001-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -23,9 +23,6 @@ # error "Never include directly; use instead." #endif -#include - -#if __WORDSIZE == 64 /* Structure describing the action to be taken when a signal arrives. */ struct sigaction { @@ -55,36 +52,6 @@ struct sigaction /* Additional set of signals to be blocked. */ __sigset_t sa_mask; }; -#else -/* Structure describing the action to be taken when a signal arrives. */ -struct sigaction - { - /* Signal handler. */ -#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED - union - { - /* Used if SA_SIGINFO is not set. */ - __sighandler_t sa_handler; - /* Used if SA_SIGINFO is set. */ - void (*sa_sigaction) (int, siginfo_t *, void *); - } - __sigaction_handler; -# define sa_handler __sigaction_handler.sa_handler -# define sa_sigaction __sigaction_handler.sa_sigaction -#else - __sighandler_t sa_handler; -#endif - - /* Additional set of signals to be blocked. */ - __sigset_t sa_mask; - - /* Special flags. */ - int sa_flags; - - /* Restore handler. */ - void (*sa_restorer) (void); - }; -#endif /* Bits in `sa_flags'. */ #define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */ diff --git a/lib/libc/include/s390x-linux-gnu/bits/struct_mutex.h b/lib/libc/include/s390x-linux-gnu/bits/struct_mutex.h index 571265267c2edbc388e00aed800c03b3d2c05b2d..d7b3a380e8f2f32e96a7d8f9b3fe71c52d2bf7a4 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/struct_mutex.h +++ b/lib/libc/include/s390x-linux-gnu/bits/struct_mutex.h @@ -24,39 +24,17 @@ struct __pthread_mutex_s int __lock; unsigned int __count; int __owner; -#if __WORDSIZE == 64 unsigned int __nusers; -#endif /* KIND must stay at this position in the structure to maintain binary compatibility with static initializers. */ int __kind; -#if __WORDSIZE == 64 short __spins; short __glibc_reserved; __pthread_list_t __list; # define __PTHREAD_MUTEX_HAVE_PREV 1 -#else - unsigned int __nusers; - __extension__ union - { - struct - { - short __data_spins; - short __data_unused; - } __data; -# define __spins __data.__data_spins - __pthread_slist_t __list; - }; -# define __PTHREAD_MUTEX_HAVE_PREV 0 -#endif }; -#if __WORDSIZE == 64 -# define __PTHREAD_MUTEX_INITIALIZER(__kind) \ +#define __PTHREAD_MUTEX_INITIALIZER(__kind) \ 0, 0, 0, 0, __kind, 0, 0, { 0, 0 } -#else -# define __PTHREAD_MUTEX_INITIALIZER(__kind) \ - 0, 0, 0, __kind, 0, { { 0, 0 } } -#endif -#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h b/lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h index e532dcddf63eef3facc4ec0021639de7ca1b49bc..7d453256eee76416816427df60aca51e65a76466 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h +++ b/lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h @@ -28,7 +28,6 @@ struct __pthread_rwlock_arch_t unsigned int __writers_futex; unsigned int __pad3; unsigned int __pad4; -#if __WORDSIZE == 64 int __cur_writer; int __shared; unsigned long int __pad1; @@ -36,23 +35,9 @@ struct __pthread_rwlock_arch_t /* FLAGS must stay at this position in the structure to maintain binary compatibility. */ unsigned int __flags; -# else - unsigned char __pad1; - unsigned char __pad2; - unsigned char __shared; - /* FLAGS must stay at this position in the structure to maintain - binary compatibility. */ - unsigned char __flags; - int __cur_writer; -#endif }; -#if __WORDSIZE == 64 -# define __PTHREAD_RWLOCK_INITIALIZER(__flags) \ +#define __PTHREAD_RWLOCK_INITIALIZER(__flags) \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags -#else -# define __PTHREAD_RWLOCK_INITIALIZER(__flags) \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags, 0 -#endif #endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/struct_stat.h b/lib/libc/include/s390x-linux-gnu/bits/struct_stat.h index 3d77809e22d16b08b9329cb01c33a48e61177218..47141080639b92a6607dabed7ef00d3f53143736 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/struct_stat.h +++ b/lib/libc/include/s390x-linux-gnu/bits/struct_stat.h @@ -25,7 +25,6 @@ #include -#if __WORDSIZE == 64 struct stat { __dev_t st_dev; /* Device. */ @@ -62,70 +61,8 @@ struct stat __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */ long int __glibc_reserved[3]; }; -#else -struct stat - { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - __dev_t st_dev; /* Device. */ - unsigned int __pad1; -# ifndef __USE_FILE_OFFSET64 - __ino_t st_ino; /* File serial number. */ -# else - __ino_t __st_ino; /* 32bit file serial number. */ -# endif - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - unsigned int __pad2; -# ifndef __USE_FILE_OFFSET64 - __off_t st_size; /* Size of file, in bytes. */ -# else - __off64_t st_size; /* Size of file, in bytes. */ -# endif - __blksize_t st_blksize; /* Optimal block size for I/O. */ - -# ifndef __USE_FILE_OFFSET64 - __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ -# else - __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ -# endif -# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif -# ifndef __USE_FILE_OFFSET64 - unsigned long int __glibc_reserved4; - unsigned long int __glibc_reserved5; -# else - __ino64_t st_ino; /* File serial number. */ -# endif -# endif - }; -# endif #ifdef __USE_LARGEFILE64 -# if __WORDSIZE == 64 /* Note stat64 is the same shape as stat. */ struct stat64 { @@ -138,7 +75,7 @@ struct stat64 int __glibc_reserved0; __dev_t st_rdev; /* Device number, if device. */ __off_t st_size; /* Size of file, in bytes. */ -# ifdef __USE_XOPEN2K8 +# ifdef __USE_XOPEN2K8 /* Nanosecond resolution timestamps are stored in a format equivalent to 'struct timespec'. This is the type used whenever possible but the Unix namespace rules do not allow the @@ -148,66 +85,21 @@ struct stat64 struct timespec st_atim; /* Time of last access. */ struct timespec st_mtim; /* Time of last modification. */ struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -# else +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# else __time_t st_atime; /* Time of last access. */ unsigned long int st_atimensec; /* Nscecs of last access. */ __time_t st_mtime; /* Time of last modification. */ unsigned long int st_mtimensec; /* Nsecs of last modification. */ __time_t st_ctime; /* Time of last status change. */ unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif +# endif __blksize_t st_blksize; /* Optimal block size for I/O. */ __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ long int __glibc_reserved[3]; }; -# else -struct stat64 - { -# ifdef __USE_TIME64_REDIRECTS -# include -# else - __dev_t st_dev; /* Device. */ - unsigned int __pad1; - - __ino_t __st_ino; /* 32bit file serial number. */ - __mode_t st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - __uid_t st_uid; /* User ID of the file's owner. */ - __gid_t st_gid; /* Group ID of the file's group.*/ - __dev_t st_rdev; /* Device number, if device. */ - unsigned int __pad2; - __off64_t st_size; /* Size of file, in bytes. */ - __blksize_t st_blksize; /* Optimal block size for I/O. */ - - __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ -# ifdef __USE_XOPEN2K8 - /* Nanosecond resolution timestamps are stored in a format - equivalent to 'struct timespec'. This is the type used - whenever possible but the Unix namespace rules do not allow the - identifier 'timespec' to appear in the header. - Therefore we have to handle the use of this header in strictly - standard-compliant sources special. */ - struct timespec st_atim; /* Time of last access. */ - struct timespec st_mtim; /* Time of last modification. */ - struct timespec st_ctim; /* Time of last status change. */ -# define st_atime st_atim.tv_sec /* Backward compatibility. */ -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec -# else - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atimensec; /* Nscecs of last access. */ - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtimensec; /* Nsecs of last modification. */ - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctimensec; /* Nsecs of last status change. */ -# endif - __ino64_t st_ino; /* File serial number. */ -# endif - }; -# endif #endif /* Tell code we have these members. */ diff --git a/lib/libc/include/s390x-linux-gnu/bits/typesizes.h b/lib/libc/include/s390x-linux-gnu/bits/typesizes.h index 5302d79b87a3bcdf2e8f9052fc3404030f9a3b35..101d3a7a9867d31f59c32464807cd473ced919fd 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/typesizes.h +++ b/lib/libc/include/s390x-linux-gnu/bits/typesizes.h @@ -57,42 +57,34 @@ #define __TIMER_T_TYPE void * #define __BLKSIZE_T_TYPE __SLONGWORD_TYPE #define __FSID_T_TYPE struct { int __val[2]; } -#if defined __GNUC__ && __GNUC__ <= 2 -/* Compatibility with g++ 2.95.x. */ -#define __SSIZE_T_TYPE __SWORD_TYPE -#else -/* size_t is unsigned long int on s390 -m31. */ -#define __SSIZE_T_TYPE __SLONGWORD_TYPE -#endif + +/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with + g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was + unsigned long int on s390-32. + Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the + generic version as both types result in long int. */ +#define __SSIZE_T_TYPE __SWORD_TYPE + #define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE #define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE -#define __CPU_MASK_TYPE __ULONGWORD_TYPE +#define __CPU_MASK_TYPE __ULONGWORD_TYPE -#ifdef __s390x__ /* Tell the libc code that off_t and off64_t are actually the same type for all ABI purposes, even if possibly expressed as different base types for C type-checking purposes. */ -# define __OFF_T_MATCHES_OFF64_T 1 +#define __OFF_T_MATCHES_OFF64_T 1 /* Same for ino_t and ino64_t. */ -# define __INO_T_MATCHES_INO64_T 1 +#define __INO_T_MATCHES_INO64_T 1 /* And for __rlim_t and __rlim64_t. */ -# define __RLIM_T_MATCHES_RLIM64_T 1 +#define __RLIM_T_MATCHES_RLIM64_T 1 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */ -# define __STATFS_MATCHES_STATFS64 1 +#define __STATFS_MATCHES_STATFS64 1 /* And for getitimer, setitimer and rusage */ -# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 -#else -# define __RLIM_T_MATCHES_RLIM64_T 0 - -# define __STATFS_MATCHES_STATFS64 0 - -/* And for getitimer, setitimer and rusage */ -# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0 -#endif +#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 /* Number of descriptors that can fit in an `fd_set'. */ #define __FD_SETSIZE 1024 diff --git a/lib/libc/include/s390x-linux-gnu/bits/utmp.h b/lib/libc/include/s390x-linux-gnu/bits/utmp.h deleted file mode 100644 index 87db119de9415b8be0386c7bca655c4046fb2e36..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/bits/utmp.h +++ /dev/null @@ -1,127 +0,0 @@ -/* The `struct utmp' type, describing entries in the utmp file. GNU version. - Copyright (C) 1993-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _UTMP_H -# error "Never include directly; use instead." -#endif - -#include -#include -#include -#include - - -#define UT_LINESIZE 32 -#define UT_NAMESIZE 32 -#define UT_HOSTSIZE 256 - - -/* The structure describing an entry in the database of - previous logins. */ -struct lastlog - { -#if __WORDSIZE == 32 - int64_t ll_time; -#else - __time_t ll_time; -#endif - char ll_line[UT_LINESIZE]; - char ll_host[UT_HOSTSIZE]; - }; - - -/* The structure describing the status of a terminated process. This - type is used in `struct utmp' below. */ -struct exit_status - { - short int e_termination; /* Process termination status. */ - short int e_exit; /* Process exit status. */ - }; - - -/* The structure describing an entry in the user accounting database. */ -struct utmp -{ - short int ut_type; /* Type of login. */ - pid_t ut_pid; /* Process ID of login process. */ - char ut_line[UT_LINESIZE] - __attribute_nonstring__; /* Devicename. */ - char ut_id[4] - __attribute_nonstring__; /* Inittab ID. */ - char ut_user[UT_NAMESIZE] - __attribute_nonstring__; /* Username. */ - char ut_host[UT_HOSTSIZE] - __attribute_nonstring__; /* Hostname for remote login. */ - struct exit_status ut_exit; /* Exit status of a process marked - as DEAD_PROCESS. */ -/* The ut_session and ut_tv fields must be the same size when compiled - 32- and 64-bit. This allows data files and shared memory to be - shared between 32- and 64-bit applications. */ -#if __WORDSIZE == 32 - int64_t ut_session; /* Session ID, used for windowing. */ - struct - { - int64_t tv_sec; /* Seconds. */ - int64_t tv_usec; /* Microseconds. */ - } ut_tv; /* Time entry was made. */ -#else - long int ut_session; /* Session ID, used for windowing. */ - struct timeval ut_tv; /* Time entry was made. */ -#endif - - int32_t ut_addr_v6[4]; /* Internet address of remote host. */ - char __glibc_reserved[20]; /* Reserved for future use. */ -}; - -/* Backwards compatibility hacks. */ -#define ut_name ut_user -#ifndef _NO_UT_TIME -/* We have a problem here: `ut_time' is also used otherwise. Define - _NO_UT_TIME if the compiler complains. */ -# define ut_time ut_tv.tv_sec -#endif -#define ut_xtime ut_tv.tv_sec -#define ut_addr ut_addr_v6[0] - - -/* Values for the `ut_type' field of a `struct utmp'. */ -#define EMPTY 0 /* No valid user accounting information. */ - -#define RUN_LVL 1 /* The system's runlevel. */ -#define BOOT_TIME 2 /* Time of system boot. */ -#define NEW_TIME 3 /* Time after system clock changed. */ -#define OLD_TIME 4 /* Time when system clock changed. */ - -#define INIT_PROCESS 5 /* Process spawned by the init process. */ -#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ -#define USER_PROCESS 7 /* Normal process. */ -#define DEAD_PROCESS 8 /* Terminated process. */ - -#define ACCOUNTING 9 - -/* Old Linux name for the EMPTY type. */ -#define UT_UNKNOWN EMPTY - - -/* Tell the user that we have a modern system with UT_HOST, UT_PID, - UT_TYPE, UT_ID and UT_TV fields. */ -#define _HAVE_UT_TYPE 1 -#define _HAVE_UT_PID 1 -#define _HAVE_UT_ID 1 -#define _HAVE_UT_TV 1 -#define _HAVE_UT_HOST 1 \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/utmpx.h b/lib/libc/include/s390x-linux-gnu/bits/utmpx.h deleted file mode 100644 index 00ed2f21a1c4853e7f45dafe7d8ca46a0b4b44a7..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/bits/utmpx.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Structures and definitions for the user accounting database. GNU version. - Copyright (C) 1997-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _UTMPX_H -# error "Never include directly; use instead." -#endif - -#include -#include -#include - - -#ifdef __USE_GNU -# include -# define _PATH_UTMPX _PATH_UTMP -# define _PATH_WTMPX _PATH_WTMP -#endif - - -#define __UT_LINESIZE 32 -#define __UT_NAMESIZE 32 -#define __UT_HOSTSIZE 256 - - -/* The structure describing the status of a terminated process. This - type is used in `struct utmpx' below. */ -struct __exit_status - { -#ifdef __USE_GNU - short int e_termination; /* Process termination status. */ - short int e_exit; /* Process exit status. */ -#else - short int __e_termination; /* Process termination status. */ - short int __e_exit; /* Process exit status. */ -#endif - }; - - -/* The structure describing an entry in the user accounting database. */ -struct utmpx -{ - short int ut_type; /* Type of login. */ - __pid_t ut_pid; /* Process ID of login process. */ - char ut_line[__UT_LINESIZE] - __attribute_nonstring__; /* Devicename. */ - char ut_id[4] - __attribute_nonstring__; /* Inittab ID. */ - char ut_user[__UT_NAMESIZE] - __attribute_nonstring__; /* Username. */ - char ut_host[__UT_HOSTSIZE] - __attribute_nonstring__; /* Hostname for remote login. */ - struct __exit_status ut_exit; /* Exit status of a process marked - as DEAD_PROCESS. */ - -/* The fields ut_session and ut_tv must be the same size when compiled - 32- and 64-bit. This allows files and shared memory to be shared - between 32- and 64-bit applications. */ -#if __WORDSIZE == 32 - __int64_t ut_session; /* Session ID, used for windowing. */ - struct - { - __int64_t tv_sec; /* Seconds. */ - __int64_t tv_usec; /* Microseconds. */ - } ut_tv; /* Time entry was made. */ -#else - long int ut_session; /* Session ID, used for windowing. */ - struct timeval ut_tv; /* Time entry was made. */ -#endif - __int32_t ut_addr_v6[4]; /* Internet address of remote host. */ - char __glibc_reserved[20]; /* Reserved for future use. */ -}; - - -/* Values for the `ut_type' field of a `struct utmpx'. */ -#define EMPTY 0 /* No valid user accounting information. */ - -#ifdef __USE_GNU -# define RUN_LVL 1 /* The system's runlevel. */ -#endif -#define BOOT_TIME 2 /* Time of system boot. */ -#define NEW_TIME 3 /* Time after system clock changed. */ -#define OLD_TIME 4 /* Time when system clock changed. */ - -#define INIT_PROCESS 5 /* Process spawned by the init process. */ -#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ -#define USER_PROCESS 7 /* Normal process. */ -#define DEAD_PROCESS 8 /* Terminated process. */ - -#ifdef __USE_GNU -# define ACCOUNTING 9 /* System accounting. */ -#endif \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/wordsize.h b/lib/libc/include/s390x-linux-gnu/bits/wordsize.h index 8f3304644bdb1e10ae25ea828e95df45e3d4c124..5038df494751b3446f652bcb4d1c5d3e721a61ec 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/wordsize.h +++ b/lib/libc/include/s390x-linux-gnu/bits/wordsize.h @@ -1,11 +1,19 @@ -/* Determine the wordsize from the preprocessor defines. */ +/* Copyright (C) 1999-2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. -#if defined __s390x__ -# define __WORDSIZE 64 -#else -# define __WORDSIZE 32 -# define __WORDSIZE32_SIZE_ULONG 1 -# define __WORDSIZE32_PTRDIFF_LONG 0 -#endif + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. -#define __WORDSIZE_TIME64_COMPAT32 0 \ No newline at end of file + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define __WORDSIZE 64 +#define __WORDSIZE_TIME64_COMPAT32 0 \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/gnu/lib-names-64.h b/lib/libc/include/s390x-linux-gnu/gnu/lib-names-64.h deleted file mode 100644 index 0df63282ccce3e8edc6f72dc3ac75bf7a29e2b5e..0000000000000000000000000000000000000000 --- a/lib/libc/include/s390x-linux-gnu/gnu/lib-names-64.h +++ /dev/null @@ -1,27 +0,0 @@ -/* This file is automatically generated. */ -#ifndef __GNU_LIB_NAMES_H -# error "Never use directly; include instead." -#endif - -#define LD64_SO "ld64.so.1" -#define LD_SO "ld64.so.1" -#define LIBANL_SO "libanl.so.1" -#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" -#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" -#define LIBC_SO "libc.so.6" -#define LIBDL_SO "libdl.so.2" -#define LIBGCC_S_SO "libgcc_s.so.1" -#define LIBMVEC_SO "libmvec.so.1" -#define LIBM_SO "libm.so.6" -#define LIBNSL_SO "libnsl.so.1" -#define LIBNSS_COMPAT_SO "libnss_compat.so.2" -#define LIBNSS_DB_SO "libnss_db.so.2" -#define LIBNSS_DNS_SO "libnss_dns.so.2" -#define LIBNSS_FILES_SO "libnss_files.so.2" -#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" -#define LIBNSS_LDAP_SO "libnss_ldap.so.2" -#define LIBPTHREAD_SO "libpthread.so.0" -#define LIBRESOLV_SO "libresolv.so.2" -#define LIBRT_SO "librt.so.1" -#define LIBTHREAD_DB_SO "libthread_db.so.1" -#define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/gnu/lib-names.h b/lib/libc/include/s390x-linux-gnu/gnu/lib-names.h index ad6471507a48c834a5c8cbc13cd851c2e20b74b9..b76efce6d28b32d6d22ad38b1239a620cf950a8a 100644 --- a/lib/libc/include/s390x-linux-gnu/gnu/lib-names.h +++ b/lib/libc/include/s390x-linux-gnu/gnu/lib-names.h @@ -4,13 +4,28 @@ #ifndef __GNU_LIB_NAMES_H #define __GNU_LIB_NAMES_H 1 -#include - -#if __WORDSIZE == 32 -# include -#endif -#if __WORDSIZE == 64 -# include -#endif +#define LD64_SO "ld64.so.1" +#define LD_SO "ld64.so.1" +#define LIBANL_SO "libanl.so.1" +#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" +#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" +#define LIBC_SO "libc.so.6" +#define LIBDL_SO "libdl.so.2" +#define LIBGCC_S_SO "libgcc_s.so.1" +#define LIBMVEC_SO "libmvec.so.1" +#define LIBM_SO "libm.so.6" +#define LIBNSL_SO "libnsl.so.1" +#define LIBNSS_COMPAT_SO "libnss_compat.so.2" +#define LIBNSS_DB_SO "libnss_db.so.2" +#define LIBNSS_DNS_SO "libnss_dns.so.2" +#define LIBNSS_FILES_SO "libnss_files.so.2" +#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" +#define LIBNSS_LDAP_SO "libnss_ldap.so.2" +#define LIBPTHREAD_SO "libpthread.so.0" +#define LIBRESOLV_SO "libresolv.so.2" +#define LIBRT_SO "librt.so.1" +#define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" +#define LIBUTIL_SO "libutil.so.1" #endif /* gnu/lib-names.h */ \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/gnu/stubs.h b/lib/libc/include/s390x-linux-gnu/gnu/stubs.h index 120171a87ae7a525497cffc5786ed0383b47ca33..636dc73283f9e3508fca4713d7d911f47d284387 100644 --- a/lib/libc/include/s390x-linux-gnu/gnu/stubs.h +++ b/lib/libc/include/s390x-linux-gnu/gnu/stubs.h @@ -1,12 +1,16 @@ /* This file is automatically generated. - This file selects the right generated file of `__stub_FUNCTION' macros - based on the architecture being compiled for. */ + It defines a symbol `__stub_FUNCTION' for each function + in the C library which is a stub, meaning it will fail + every time called, usually setting errno to ENOSYS. */ -#include - -#if __WORDSIZE == 32 -# include +#ifdef _LIBC + #error Applications may not define the macro _LIBC #endif -#if __WORDSIZE == 64 -# include -#endif \ No newline at end of file + +#define __stub_chflags +#define __stub_fchflags +#define __stub_gtty +#define __stub_revoke +#define __stub_setlogin +#define __stub_sigreturn +#define __stub_stty \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/sys/ucontext.h b/lib/libc/include/s390x-linux-gnu/sys/ucontext.h index a766145563a3c44816cf2985502cfc5f11507948..950d26f9b433db86e9b9df218a23aff1cc3e37e8 100644 --- a/lib/libc/include/s390x-linux-gnu/sys/ucontext.h +++ b/lib/libc/include/s390x-linux-gnu/sys/ucontext.h @@ -45,11 +45,7 @@ typedef unsigned long greg_t; the register set is an array, we make gregset_t a simple array that has the same size as s390_regs. This is needed for the elf_prstatus structure. */ -#if __WORDSIZE == 64 -# define __NGREG 27 -#else -# define __NGREG 36 -#endif +#define __NGREG 27 #ifdef __USE_MISC # define NGREG __NGREG #endif diff --git a/lib/libc/include/sparc-linux-gnu/bits/cloexec.h b/lib/libc/include/sparc-linux-gnu/bits/cloexec.h new file mode 100644 index 0000000000000000000000000000000000000000..153b5491cd5cfc283387276a0c6b4b2ae6fb45d8 --- /dev/null +++ b/lib/libc/include/sparc-linux-gnu/bits/cloexec.h @@ -0,0 +1 @@ +#define __O_CLOEXEC 0x400000 \ No newline at end of file diff --git a/lib/libc/include/sparc-linux-gnu/gnu/lib-names-64.h b/lib/libc/include/sparc-linux-gnu/gnu/lib-names-64.h index 7e53ae0eb3f6bb5ea6f99a2c1e5de7cca1491685..ca08483aab3e398663087d84f914fd0903d98232 100644 --- a/lib/libc/include/sparc-linux-gnu/gnu/lib-names-64.h +++ b/lib/libc/include/sparc-linux-gnu/gnu/lib-names-64.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/stubs-64.h b/lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h similarity index 100% rename from lib/libc/include/generic-glibc/gnu/stubs-64.h rename to lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h diff --git a/lib/libc/include/x86-linux-gnu/bits/struct_mutex.h b/lib/libc/include/x86-linux-gnu/bits/struct_mutex.h index 13c9894ad4b3156677a2475ede4c0bc47d1df68a..70b516b1e5d32ca6c8b99c393ad62b7f086723ab 100644 --- a/lib/libc/include/x86-linux-gnu/bits/struct_mutex.h +++ b/lib/libc/include/x86-linux-gnu/bits/struct_mutex.h @@ -59,4 +59,4 @@ struct __pthread_mutex_s 0, 0, 0, __kind, 0, { { 0, 0 } } #endif -#endif +#endif \ No newline at end of file diff --git a/lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h b/lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h index 26bcb6482efed72a960e0f0d5f79aee819f683b4..e570e8dc72828087c96f32b08a0150a17f709224 100644 --- a/lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h +++ b/lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/lib/libc/include/x86-linux-gnu/gnu/lib-names-x32.h b/lib/libc/include/x86-linux-gnu/gnu/lib-names-x32.h index 735e8e2d3907906c879428d5433b19c9f8065b24..0ac184ea85c124f89fa21819b5c36c7e16e031ad 100644 --- a/lib/libc/include/x86-linux-gnu/gnu/lib-names-x32.h +++ b/lib/libc/include/x86-linux-gnu/gnu/lib-names-x32.h @@ -24,4 +24,5 @@ #define LIBRESOLV_SO "libresolv.so.2" #define LIBRT_SO "librt.so.1" #define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUNWIND_SO "libunwind.so.1" #define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/tools/process_headers.zig b/tools/process_headers.zig index 3e912c742e79c4c89d242d72a3e8c7126741c3f7..976f17b18207bd12bd915a64b4318d9543e63399 100644 --- a/tools/process_headers.zig +++ b/tools/process_headers.zig @@ -36,6 +36,8 @@ const glibc_targets = [_]LibCTarget{ .{ .arch = .aarch64_be, .abi = .gnu, .dest = "aarch64-linux-gnu" }, .{ .arch = .csky, .abi = .gnueabi, .dest = "csky-linux-gnu" }, .{ .arch = .csky, .abi = .gnueabihf, .dest = "csky-linux-gnu" }, + .{ .arch = .loongarch32, .abi = .gnu, .dest = "loongarch-linux-gnu" }, + .{ .arch = .loongarch32, .abi = .gnusf, .dest = "loongarch-linux-gnu" }, .{ .arch = .loongarch64, .abi = .gnu, .dest = "loongarch-linux-gnu" }, .{ .arch = .loongarch64, .abi = .gnusf, .dest = "loongarch-linux-gnu" }, .{ .arch = .m68k, .abi = .gnu }, -- 2.54.0 From 2579b37ff6e7f08fe90cf920a83e1282e51c571e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 29 Jul 2026 08:39:36 +0200 Subject: [PATCH 084/215] libc: update glibc abilists to 2.44 --- lib/libc/glibc/abilists | Bin 248691 -> 253117 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/libc/glibc/abilists b/lib/libc/glibc/abilists index 3dec0a31a51a74d915e94a8c647416555d175a13..16ce0e77b3a4af2e7db96148dfbd4e4857b5fce8 100644 GIT binary patch literal 253117 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 B&9DFf literal 248691 zcmc${Taz5gc_o-xRVV;ltQvdc&hDyb!QGX(+$CiIx~;8cwhwq3vwd3A!#)S{5?Pf% z-jJ8N@F|mMuzSYTBqUNJjo56mS5ku%i``{?LBFZ>5A+wvml>NU&eQHA_ngn&Bith+ zqQc#ChHVr|C{#s8c({L;^PTT}H^!}AYt(Pe)5Uaj(wZ%g=V_W^CUWoxw@j#_W- zwOV^^{I9*&-rH;M@9nklWsm>i|3BE#e;T zt-YJAy|1+P{BGUhu;*S;|fu{nK~uwmw`xXyGP){ZBVr z@^Odj%Z0kc_tn)SZn)R!E(TcU?|=E*-{SJOTNe*oKUbfJ2U=e)hvRfK?R7@63-f>e zU&%lWRNMle_7?rsEb?Z~`tzhWKc6ihr{|sd5wDiN@GD>T=2?=!=q8f|_D$=R{pYv$ zFCOl5zdXIU|7`tWUpCA>H_X0ln0?tW`?6u4zDSbgXptPH%cRrCeN1OdY?6Qeo&RUh zAC3n&f>m!KNrq}uCHA}c;Cg$re*afbxdoeSRqRnL;iT7Dq`k4djsX|aE+-kUmg!k% zxtu4%$#B{FE&jXN{zy(l`|_28=eG|o9v;YfI>3=RkmWhx@*K$W9LVw<$nqSh^Yj*$ z7%S9IN5gUCyG{~3?{YdC#V#Ayzc;}tjlEE(f6|%sQa+cqF_l|xeRK0{o{l@iNk5&B zT5{Z5&-EdNeZtNW)9}u%7T2>S>)Dd^Y{_~mgK@K^?9&?dX*Qh6M@QI<0hWP#@b=Hl zMc&?Tw|=&@{~p48*4j(i9b5zK3#`Fadt!n!*BPhD9B;GR={?3#`Tu@!bN?^&`Lhn* z`i?qn`^sKEz3ffvt=v&(Jnq!l!IQyhxyki8dBy?saq>racRyL*SpRG=ouw0Nlj9(^ zc%-qU&5pF?eQ0FU`FuLJt{3LUrrpI7OPri2KbG{4^>Vj=s9(BeZCq~%6Z1#o6`v2L zY1x?^?_%Tj;5(MEj=A>;F<8^Z@GL?6a5@olwMdtX-f`MT(A9D6jL%!0r@fQ$LcEAM z58jbOgq`d#BuvKXxHmg*y|Q_pBnTxY_)F3~e_f)9Bw0tEIwq8(C}zzp98wn=1y%m zNtbWXnGUBD-nVmGxc&C`Z1c3WVd>F3eWW0dJ4rZC|LjCb9KMBI=r0bujLn4aci-GVUBDlhv48 zT!N9-$Jn)uX4ReEe~m{(#{~R=S2myU)XaEjQ~*9$oKJez3i`jz;1hj*Z_s+Bb^8m; z%eTJB-2AIw(9hq(pZM|>e!0{7eSXoe<7Vp`|0bb3&J=d_`3@bksztBjZWWl6g%itJc4dfDuQ3g6twblfmtF7Zbcz#Cz5eHrZUAyFyf?&=Uro zi&@$m4u*L9VUg=#46Dgqh#gqien>KV>0*(L=jkX#1TO#l%I0#=88OF#sZ~ekUpF{9 z64&Z5J~krF4zPqc!!%7L_e9Qmk-yK%w}}-W5vB;+XIbh@4|W`Tk z^{@W@Z(mt|mi);q=?_m@JQeNDGweKxkgz@D92Z{MQFm~KX$1BHD|A-5c4o7vWFI$t zGqY8+X2rQCKC5<0-IL ztc(|$0Go3J8#s1WgIU1Sz$`$ln3zE8B{2s2er*iYV^mlNI`P#{I+M&;2O?x01edd+ zWo6c%!vN2F%TYqK3C`s=U%tJ+`3Qm4;)sx3bECL8>CHQ*z;=)K zXE;URyj;yEcxw`B<+#t`^V^3P4-fG{Z?D^j0#e;Lgnc;_{O6E(#i8I8hk{oe3SRNu z7jvBGetME}n_Urgaw82)k|LX=^&_H}TY1WS@njCfLeA>?r9$tJ-l{E<pQph zxFz;vOYF&(*pn@>ry#-aJR2@fdrR!#sE-x+Gd{_J!J3{n*?M?et0nSEpjMIhjol-V zOyp&fT(iusM4XEe_@rdtO zc=~}9p2pLYG*O|FidQa?)*Vk5OTwv0qV&rouBuotPd3a z*_=>B5B;Q{VlPgM`?>Y5eF$#1Z@mjEe7pS>ekoKpukm|pl`WV`4t^arTS4~fR}a*$ zx`mu;?=r=yt82|rgiEj=RgTntVQ(JU;0QUd3`?gyfI0(((5o%}$zs{>CEejNIUV+w z#|Z#w^$(wl?QRq|5PS_*=c9E)X-F0K~tN{9%4oUKc>19km{xLfqexW ztd@U$2wMdapMUlMi>;52buc##6wBMF zN^eZ85K0(OA_V|qK1BX>RQ6a|c42{*>pLm{dFut-VXqc^MGA+oQM}FirP}RLFK=@R zNLWG7TS$piWp@KS57H$9y7a7<&X$8w=jaNYMBv(3ytY5@O!}|C8J)zUFbRhdxyo3} z;iP~dB7i)a$J@@qd^#S?&hmKm>!`zh^NWYAZ?FXSEnQl>`$dxAM}W}VyZ+-O$!hVq zoi|yGM}Y>>Z+3!82zK1%ouhPtI&0*zOaM4`2B@dS27%@n;?_C?;Q*YMRb<5qOFDq_ zeeiqVH~Bz*0u}65U@iSy|EQEt*2iJZUrPy5u~_sENZIkC2>fT|&7V01Z`M?WE+Y6k zc_XV)bkz%HCmw15t~*`U=173{t=u9kGtfnTm1S8Qe{(S_@M^fHj{xM_{6arE$Ab1I z@;pdli6op=RdNZoGs_GzG3+kqsaQCCvYam9=B09Yyqr!PBq?Brp-8{Nxv&w)~an+9g6L`>}_LAhC6(ZnD24rH>1XrqqMW0I1%NT_wWlNHaxiHa2mayGDv9hPy~Tx9vVB$DPM1AZKg@yX?Jnp+mmE>YB4^s*!FQhDST#?k{_T(P|M7 ziKyb#$)KdUXE^CH;6LrmC-K#d@wDF`B1rfk!%Ij_^=7pxQm~=57+xCKkv!tAkx3Hp z4x1F!2r}2Fb?J^Ljs$x8Oa+3bki&5}f#R-xV~oS?}| zda~k6JIFLqIqLw#SD~e8gvhIMh`5U6t+1#YEr@9}i3FJ`I`S0BhT*L4VcWcCQa$(> z6q8npk(f8{NFZ|Xm%4$c6lKAs@w)Fj@0*eHU_z8w0%w*6w1KmJY;(c14j^r3-UmoT zC@rS=p&ZcU#7c8eLh<%Ij8%5nks(1?-xq9Lq+?Lo!338xnp0{rybIL@#ocL8UC5Fg zT^>`xWfOKbZ-b?(y4z5#DhG7!wZy@^u?q{_=|5U6P-B{oR%165^vC%L1|3aM=d*pi zck#@2^#O*dH-u3wo_Ft?SYMJZ%4&iMyl65E;R?+cuYw8#@;3=FAb;}<$lv_(kGeC| zZuHXRZ8q-YMpuyTdNX<4S&S!3wk2A>7Le)!JVu*g>{VoC>mpJq8`j4*=mud#q6_75 zPenA^-f1C5-N5QF3suNOXEeim&}`C-q2_-&dOJuQ(6Blcg12MF0#1p5rocZeC$PSd z)-(Km%TX7YP(l)$$ISjt2L&I!J-J(_w+XV3!Ac|qIj1}#6?k@viaEH^$gooMM&xfKz{;6N z%e&%%V~D&2;+?|NsrcG7$XgLqUPB@NImiEW76%&&odCyzVoA_|AKeB4?mSGeF)7{~ zi)DRnjRxqZO_OB@7Nli5+#!;|jxy6Im~~T2K++@_Rk^J7YASKRulzLwqjG%?yb7F} zRWuNc>%dxe@PPSVsk|W}Gnd~_lI#e1!8WPFkObjpt`&K&DC!TU^D)R_OZY(-_{Ewt|1%zzX8(1x}LBDiA_R(2;vIN!d*B z?X<65(-%w@fjBtp>mMwd;x`_M?Y@7oRr-Da(3tCVxW4-mX31;G>j~<9NDL=<&k#siCbLmz$z9i?M#`sI`E|Qv-~Vyv)9I2WWxV@eu~YD6 zhQCY1R#L0SmO#y)_2D9Th5!-kZ<*!I1&v*I)B$W~@B5uN6l|mUw96D4jnWN#$e_;+ z(jS_*uu)GeF`Od{!x17tnqhzI4`Fg}Q79i|F=Ou-Mf$BB@zX=-Kv-z~?W<*!fGEv$ zA#43P7Pec=twYi-6z>4anP{?7)POxrigInCe#RgyxlZZn3oq_QvUI zg4)h%p3;J)fT-krwSR0I3@nh?Bng#t>aO~(m4*W{qh7Z5Wr|RLv{Fs3SZll(vJ;Zt zY^BTJj4PWsSz+tC2%2KC65nA9r8k>}5KDyuosS3KQxZU_GUYbbQ6 ztHg}fHz{rPXmYg~GKpFZF2TG)#VUY6^F=Y>q204=l9D{YFKa7tc(t$@2M|rkQQbTz z;d@e!Q2EZhX&unkh@c<+qf*ttX>qnp=BI4{rCL(Yxg{T}FA`;B^R(q*&A@y{2?$Jp zkU!+0kHU0Ms)@RhRvAgcLX}0V4LawsI+Pg6wUnATVk4>&E%i58Lh=zGJ{{IfG-}DX{YwOK>l;sDtrfUhi0$o8E(cKlxTmd#c2Q;4_{pGmvUDzJS(~lg zVldbN>kx8o0m3-P3xrH49LIv4ilACYgI3T`rpyGdm$?vSMO4Wj86lggv3sGNxA}X) zYuV$+vW(N>r#{gH`;sG7hyy4&08y^AErHKwgK!OC!(^8BJCh}qgRGp`=Q>gtaw&TO z`6B8yBEn>CFqB!q?{L1sG)JjiNiN$g$5F{mscr*(n-Udu^4$ilHHiEQiaj{FRH}io zQjwgFTIzdoP&mSN|4=_D=iv`NdACbQd5!ueAu93w*+Ac_uq5 ze`f(pK7KrzDlq0I<$?)uqeodeTmt=$h4={BErN%P>=5Q#JLR2?0XHv^W?byce&pT> z@gryN`+Bh8V2{@0^h_#1&h86X4O2rbjaZcCQ=J`yj8N1PaT42kLoUo@xv(Bo( z6fUVw!vs>ZQTzt_uWnokA(s<<(vnl;eEF~-A6MViREnq}#uh|lgv(XV|x9F1nN(6hO676zPTt3*ft$z!aL zuE1-PAM%b*d!hvpy;F1*OSdXFE@Ac93s&BRVZX9+=}Ne&&g$%hQi%;jHfHoXC$dMs zyxIQHc9X7ST+Yu1^Kq=vq(no-gQY#x)90#YYn}5DZk{ntxzu=m|z6_ zPF;ayHstYFsZonz%x}PdKW3kdUu`CUO{QgidH#rGxM+>hIYq2d%mbXy7&7#(B9&UiZA7~F5?;8F7K$= zJC(a3rTT7dE=UC%ZS-x$>X6;=1d+1=1CVG_u<3#aJ${|mxzHPPsYE*u)PkC{mVtc5 zQZuSZ=Lv~O9{Nwy^Wz}a60 z+52?4+=bv#W~v3oFc<%1Yt>-@XNzM*q6Vk=h$bye0oh!9H93XBQog)^qBVS(HWF-% zKkgJ8#TASU05ZfRN4kAx5$rreMNjRhCIzcU_pDe0v26>vX#?&+Ucq4*qYh)a3Sc*{ z$6;Vf^iuVbeAK#ndLXmRw9{vl09(`y??P@gm7i+s1PqN~StRSSzlG?;2qIcuHH zxVk#2t6H09uuKXwP!3}|_LriMsbX4|k@lv(v81z{Vmn&UxPN>A)k^RHaiQ2CTn>k| zO#^y$FsV?Ys?o69OF&m!xY|zvC)Vs+<0VYqV*o@>V}URNM&mEU4{$a}#x7*ZZ_20#2wH43YQWLj!mR3YDo0Qdj;ifmD`r%WT(2ZT}V(Dv!_m{RxhcKe$z zAGW{oQhE_uF9Cpl>!tX@SMlX``xgGB@GZZfcE~Re+F$1v4EDSxUk^8TUrN^&VW7gi zwlLQZk=5b^#*hn%#*q?Z7l&QaVTCOt-6y+|7sY%PvUH3}ZAf^B8{!dA_j5ne%JZ!( zRui7k$Saw3isyAIM#1r93X2;;J|XMmPZEyjB#B)9+WQhYHP`U^Z9}yg_{NZ!gRSX|d`v z0R}&V>s6o-r!ww#hv7AJcM`XP z@jv#^7 zC~i$X8xaM5OiK|#?II~!2h$R&QH1J2sCa|D#SBF=V4x6-z{{(hu|@uM?bvCZ#1`H>jO8C{V~$eH=Q*Ry-t*_lmi@2;a3D&}oSrkWU5**S`aq zP&LsEstkoS${>f5&c7N~EcOFN5=Rf&Ns>(B*F8W(oGUY>>7Bb}eSyR;`qLGA@qNR1 z`OIAyMo}1^xh z35tmxrxy`z(^ePj%pV-GxAFa7`-4^F_@knLPJM??Lu|f20L~Ia!Aj*FWr?Ab1T04# zfR$sH-rH^tS+D$8r7U}2w)M4AuEfm=b#!ZoeB6j?=4N5zmS6* zI~AaAC2%L6$sEVJ2yKQol+*rwSYLC$wo|Wz4;B1ci<*M?EMig48@I3DBu79B#EMe! ztOvj8nmeXF;>0HaplErTOLg4~Tu@n&?PdaA9~z^T(0_KP72>S+!4P7mGECXwKz1ih zPo_}DxG_wz4TY1}sU-~#JPFQi?r`EG<}184|kVH5NC2$Yqf54^N;R(qae5yCQ^ITey*cKmUmm z^wxk~)Ro0mrR#|tkcpQ3l3r4`HT3FAELxkSQ`0-EMXjzE^o=N`=j< znG-F8XTuTd@p42<=!<}6?$|ZV1$G_Te?X6e=(^bQI?{ZD{Hlp<)`eS2?IA(PvAnOf zwR9-Hhy}e4VTEc_ZHYHzIgOD+QeqMs1QXYqGyJohhOu%L=Lah~b4Bs|BLiSlZ@i9) zp3b{6CC|B(xFBu@dMikRSp`l|Q}FtvQsKOa00)y1bquv%S-DU6bgGN}itLIUdDGEQ zWsaovKR!sz=UJ%CMoo5FAXVuXL0`Y15f3|LJ`h{JQyqTdc}%-48TDT%o%L&ZNcAcN zdmtG~*&axS@(UzG`6b6pVWxIa(#o6N)N5>4b(VvbjsICkEhLNwBnrn{M-md+WZe%4 zz|P)LQ4qDLH^qO*i3ki|wtfX6J^=9^M!R+kGioM-gW~L%< z9VMC~8T~&z>iREMQmn)4nf<9)Q^QJ ztV*ZQ4t8hn7@=?EDsk*Q;*?_PFW|kIY&h$FL7<8FaH|mTN~26z>Z_cmS!qf#jlWup z)MLE6bA})U@|M(4=HnF#3;qfF+;llen!J9QS11dW>Y$w`q;(XlajTJAg=BzZP39v# zM6?Rvg5U-BiRbT&o!%Ebf1f%96jjRD36<|r*D)e*PO_S#VeE0BD!O&n!{UB(613#` za(;d~mxEw!eYm*>6J2EYPP?6zs*=63c`4~|)E(LbP(th~qoFxzUSRn6R~kuZWJLgT z_+mpDTTi%7OZaaPFAR*(CbCNMUJO`B;UgM`X+wW-z!YY3P$d^(w z5_b?v5x@7wokgr%6SK?;z#^MCqu-}d1{;GhQ-mHe1ySpMYl*|EUSneQoHxwcYCjd0 zNc>h^8pc(g8rrX*;k(YNgn(P5@KKW6KDui;Gk@#O_BSA{JJG8r zyA(FfPvw@hQmxeMmdLgkLW19kpuH6wVpT&SW&*<%2iO!}Q6!wVw1bzT?s3td280i@ z;mLHFkjQU6hg6fk+lbdK@M9+QZhC;Y$D1g<(}?CJWXG1S7NazcRkTF|%iw5<}LnJiFI~Hw(#k|L!P9-$?>0>%mL!ae3FhZj%zGc7-{Ijzg7XYYUa!= znfIoB1f_XsiCfrz*A{|Z-;vzpfmVNgdZ`#oHJFtJBRlVJ-(Q!WZIaAsb*3jt?uc1# zb$d73J+N)>&xY2UTYqlC2}7iXfvrolRkrc|ub;L}<@u`zf6mpckiL5Bh4iUfh9+R! zXJ^U@n<*d`cU>V!)8PS%`kV~xvcGnb^ zPK&m)CQxyJ&#!F5XBv_G3jZqzZp%h80=#9q0IXQ(kYb*ut=*p`LHdv zm6VB-4F1dd_d8HaQdL-NY(202_z&h~n+ZHb-PTths4GqD&p6p{2SLk#s~9rrz0De3y6yiM5=~Rpb1h6O~t454~BOEb&xk&w;zlfgd?}asatjzD_D9Y z-#L312ny|x==;UK0^OS6)Nmy@bG*Tpv0{RW+mIn$yagZm0%^TVPt5d*%0o-8M(yri zrpCTDYI_E^x&CFK(1nUT+Kh#j!G^bdoijWIu9-acnOi6w=s0@I&G?i6cOqCPM5c;V z#>4?mXebjF+;l4kqfM7p`{0@$1H&+JT^}MUCw~J&ZV zY=5Iq1jKX&*e3UzU&ufY>)HWH&j>E_Xa|uK<4|oX>=V$w+zLV^Ga$QB6tC?fKhPv; zelWRh37AAN|1k#pc_iyx|9H>4#!*gp5n?JTT9G}@Q+yQwI8dmFwFNlJ5z$l=HhDFa zB&;@t-j#Gw5MQ#aO#mT5!|eLD;nPJ&Rz>~A_Y$yyW$?0i@3?~iY;cM>@7C(BFVL+< z7E?08n0dA18jY2OlZFD@|E(k#{{>ry!EEb8u50rgW(s-*oD&nbsB#@#)VfSSn2Jt> zIw*&c;&2Qu9r$z%QsiJ~{Y4s)W+TLo$|q=_EAl!*z!C{?jSVT;(pWo9aO6v6pI>!` zHe4K`&FR>QL<1JO1Pu{_lf`^h6Dc~?OGy+ z)tZwlT0`dMw==uvqED0^d9<_e*cX|rnBa6gho>hFpY1g1T(&HcU*idK7lF%0$=o=y z$_cpr5re#Y#VYi*=eMt2JiLZ!B=Dom39g}_`Od9t9Cv%?nqYj-ULZ^zV@S7ipZ?`L z#3&p~5qT9j?XjjaLZrN`IUddTB$dB4PCBRCFPmcAXq@9~#X`IDE zr-6B!#+7nn0W66!d^fXpGkL%|=lb*o38dJ~rml?byaRn`F0vdEHHroo?V;vTo8U{x z#h)-QM=PWt^{6}F>Xq011b_WXBd>+UEaS4dP!M0-iz9Y|X1aO0)EvT@-Ubs<=ofl0J3baha# zv@XXOh%FC$Cz|oyD0gmLcP=z{pl4shH^5E5jG|l#*rsWpmB>$^s+rDYze zC4G0~D^clmo*!&?>q#4D^ruXwlOakx!*8byD+Svr$*_PaJ%TOIv{(budRR0hFp>9r z+AH*kgd{+sUa1H`IMuQ26CBH#ieFz@e`Y9U$*Gc?a30qy&_~a}?Bw;ubT#j#a75^q zx36_IMjSuMS99icXpZ=sAh9rIo-C(B>~=xhNsUE#00U`yw|H-V-hgw14Z%4+_G1P3 z7Z;4eU16k=Y67d-&hQR+ZAF2C9w0T#;&PBJocI%fphgO`3RY0F0%(ro#|1F0mH{%b zU5dc;uNy2TerYyy(4&x(!3rTpIk@k{XWPoG2w2G~J7V;d^q^}}U?8IqJz_yZ@gnqy z1;BRj90$@nhBUEPm^2VfrZ`m2KMy@Y+!{v^ZXPacD!3HrxZTLzYE+pO~` z^wtX;)j^*a+`#nJTml@LK!#@AjTL(dn`~sN{ ze$g@=H(S^EH_D$`%Kgg5+u|h0D6(=~$Zx)cTvPk!Fj9)yC2oSEKNaO+6FV(TG26!4 zB+#hinv8}EOyG@l8d&%hXW-_k9b&^wJ=3C3)zRW%EYnVR$kC6z(Hwaq<Ae?Y>CS9cGT?KFra;Mp(N&=_MzCW z$w$_rct@VC%k|eb8(nTS^?^TtlFc{2c-Z;|)oZ?`G-|%iFWB{WzaUB0u$iECF1d3S z`YW~JI@rfx2k!RrUql7%4m2p{oDx<1t8}vx;UX`z?jXeOffdAdM0*ck^xhOBrBOf> zvZcKfEc_kxcMA7CKa(N1thDwl+^#}v4;Ek-W3`}zEoR(|PqG)Baq#ce6FCIs$#T4s z>Uffz&5n{TRI$ti7aa?RtPP$y>72}t&leakTaeEUh`f~w6JQZ;Lri|I5@FKXfHhH} zR+y^!2~vE{ESYcx#)#5?6afZK7XmrGl z;WF#!Z7zzwMRvJ_9$5)j&TBDl@-~_4%l~w-=mMiZOjf}6;HA%*>sX=;IVA9F?2-n{ zh-q+zkecJHNzGB!|DpITVT&EJu$2fg4Ypx!gW$9RlzPM_LM3JgE$_+bjBIP`mekR& zY(&w;!ke3Cs$u7Rm^$Rw5X)g|J)lh#rP3SJc})0>Lz^u=-btZWbnsWV4=y+yy)mV8NRz0Il~($A3_~Gjww#tWemuZd^2!0#h!nlkUNVvge3xRXj#I!B z!fQPzsK1(p^b(Th%2Yz(1&?`425BF%PY@DM&w43mcx1>U3n?w=WHy-ci3El`K^e|tc-x=D3GPUg+iYv3EZMN# z9gTgZrH_PL6-6@gA{lvrd?8b%$oqeh?krD>UA5T#_@8w=1LA(;76&0Ts4CJFe za(WOh25fMs3Dt#ySecnJkVpAomDLYSP^*+3ZQD{r<3;_T4jRfeE@bJ@L4l6cyvYDN z2Rs5Rx~Lm9f`Oou>2f$YFD`l`M<_73<+K7KaI*_c6Gb0%_#V_iFs(ak0}4pYFiR~* zbqB8Lp?rq=$M9$}MVDceAu|u8HHk!cfuXq-WCU(#m|7N+GS$+l(XcEhV&OEMaaFCy zX%Ly=+~D9^M`L|~&vngvh;2gYLXWGscrIx9#lzOmp>-nE0c6ITeL2O_`a_TfIuSQJ=zY-4NbafhKS3T(`I3gII6YQ7G3 zjy9J$$7WcU33-vZ^_hw+RkoSE><$7F*gY3=ld-;$k=z(~{IqxP4WWRm=5gjLav3E4X+l+wO2Uf<9t(FPQjgrD?q7)>u5*YG6$b1{NXf zWX+0Nam+DPOd8AsH||SA2vC> zS*s6eIdzL9`Z2XXp+dTm*>06R3faca`sbZ}O~&F57K*A=ux2UZdp9f=E{#3!RF_v* zPx3acHKx^U*2F@~N&-cD z&q+h5>&`=)8B((VTETgT} z1;TS|39BKl!NG2VEaw9P>91;yjKl!tg$C9`aNMKgG<0jFlUV4E$!u87LMD%^kprVn z7YUiIeuh&7f#wJM@NHEh%|-|oW| zC=;$2DPB7Uhgs({7Hc**{Op1BtybdK;`#H%0rBt(Q2bc3_~*`w7o-eLmZlDcnm%_4 z(6jO_1oNu9!VxMWK&x#Gr<{J}s9t|EuR*m*11yRBB?=k%E;q~x+Fb*%ODpp-(>PS( zWturZHG4+khelr8nz}_PIddqs?v>4_s0To)BpssNxbX3r z^&^N}RT(EQ=ZbI(WtBp(rRP0q0-*Jen+vl@PL0USvJcDvDRI$HPq1Y%Q6hEX2~ydd z0Ch{L3xR#b}48LkMnQg1+N{CtCNv|HJ&bT2Vu6tO#C8G5TPbrRm zvz!A$HPz(U-%ZCTd*=+(`ZL*dz119ZJ%m$Qy6w~qFe|JMD3wv@h6Q!U0S8zNjuLqT z)5O@pw3Wh42eyM6`1h|`-$5Cv&xFsYm2*F0h zBK6uOyp087W3nz!-4Q50h@eP%H51SU3VHiq51WOo)Pzjk&U`*h=NdFa3Nzi}c;peKk}a<2c4m3Eg7b<~1{z`G@A&{R3*!gg%d4G#4(@`Q^FJ*S4!g+*yE8$pb-X-RVy!BYXH?h^atY)r+s!jFfAOcKoPu zEY273{+=)u+yd-fa+-D?cUG!A?saC(Mt5?9`Lw&*;&e!4QO~=E4Fx@d^x`cm=HRqf z*3wK6VJ5QMs6>}(VD$BofOPr-8`##;$4tSYQi)Q#(xz^Bz_Lj|R!-YW7asZGri-#T z(9`F^Q4Hu6OISF7Fr0p9ILoej(r_IB028s3abtwCu%BWRzbv!V0z$&IR3*tKt@q}< ziAUjiVN)0si8^tbV*b$v{f-qFhrB>?kL-{ywdFQkcx+||$8L8yGIdpr1Ht)dAC>R#>N9Tcj z+nHJKw{}lJT6Lypf%zIxcEn|4NF?G+mnW{)l3Ld$TgS#ja=sd1SSL2bF&$5KPL#utMLg*Fr0 z6Khh&mcG0{0-o`6Ov$^S*qsm|FVyr|vOcJBor>;Wtt@B)a?Hxpu+U8|;q+eQ#|nDSBz~D4y|?V)NYI0A z-6v-@wO_hb`75J6m?Tw7$W2nn;-USSMsn+(8W>nb|A{kbqQ-8!!vLcQaw_mxHgIo0 zhMzryP!4eKxCQMil53%a(MWBTJ7m)DBFK(K^A#?fAL8u_k$7qblkprrHK@Yc2iS++ zajmi^2B`cz=?iJB4^#1oL?^YJN;GA2iKu{*AjkGm3J5T`@dvTVfwA<=MYR)h?7il~ z*1ij->1EWAfM?2YN7uF-ZHph23KomCmle*s+!^TBq1lRTwU~8IC#q~?$<`DKIDWdE zMvtVXY(QUw3O1}p7F~u|zM<+qQmC@ZMVipe*xiK?{%TGm-YNLlPa^M9eVh=W3?W8o z=MEQVeY6e5nmqWV)$+_WodMfUq5bjC%FaD2kWz%WiqH-f6|xXj`OBgGO6z(3i5m>h zFxd?fQEZa~c1ioQi~Jl&Ac$4CCV)WTrT6Z_F5doB%S7eQ?b@d*iv7v|(fX9IYdPAU zhq$UHQ+Fc&h`pu!*fsMxbZo@#49$V<$Chy5&ZyD=Ot^EdigfJ{Z5lG-o)>HUhl~{O zfK~i*vWe22IWshqdVL{YCekCJVz@vV9Br+g;RH91YExZ_Fq<`sbsHYxSUqz3k}V7M z)%N$Rk#>{6Y8i$0C70&L<|ne3urfL--*)IEk1bYw@k;N^YWmCg6MpQmIvWoah5OEF z_rb!1-v?3=YN4)8WB4^Mr)cLCIQo+!_w5!&Sz&y_SNP@5Aq!Ox4rNo_{OWQL5K4Jvb0>?fyX!D$)CAxc#+{j8Yx3@Evg%uM$L<9T&H{{=cM9XfS>)fC= z)~mpU0mC@!41<~MOtT3J9k`xzHvCh2R8wnLM~7!7N8esP-DXr{FO+r;E4YY0b<1;; zG9YXaJWU0U0XL03Tk(&|y2rh}awK><8usEUTmDcm407!&T1~JGA_}^odr{Y&+Lv~m z>t|X`&&J$uAJdAEP8<-My) zCq&s)HeZ}h=Y1SZ>+SpIGVS);*oF*7S7@~`{`4gzH_D?@ z#CmX^%X8RK>r+Gai^<$e`Z@=_bH3z464Xy%qGUxMY5dA z{aWM)NsZ%l2*x?alP9Mn*MRT>EtZaRVV|AO+j`ykZGXEm9LR7yh`Ud)PpymDFQEx$ ziT%k9DfzDiwp;lxhtSagxwsAtWPBsjd29_7zKtEY&7xDN*{sqz+1n6&2!i%$v86@p;S9`mh}3n<0zyH}?@3*S3Z|ePN!Rkm_juCLbR9T=7V_jxd*VjvI-B>R?q+JN6|A6nmF%x#@6j-sPg7!M#+V(7EsaIai{e*5~x!|PO` zdfL8@$ojf8h+ZeH_qtRUuM4gBx}YW38GNsAy#1`?o!Tu-;Eu98dw3)y#Ed_x@w||w zl@D}Ul`^dgl4@4~3SPUPNO0xD+!j*r4n%9z>`m*XhdiV7CS|FUNsWZ~g-~;SSvE+k z0g{56_f9Al#Ia65EOoZf<`SD;c)}##IST-@@-G`zt4T7V$>r=C8B%6l24_FCuP2+L zi`osQ_MjWbx^Bq(853#(N*#F_7B7f8--h(PXpG@rTI=;ckhMY;d^v!%NPph-ZgM}G z<=++CO_KSV999ZpbxE#yh@2-2lNZ@TCy+*6`hZcHoxW?Qufr@8f@s>E72swNUW)#w z1GX?_!mbkDXeO^4fLTg2Yy8*}(*w15JlvMBxT3tlFwqELj3I*4bJYqxPTl6&7;Uy4 zJ4yHW?Mz-8I|=)9+*!nOB?=0>g@j3WEk{}g)s4)02hb0oJ?#&b{rvSm-OP$#nC(YU zyv9x7{gKotqc~NV)~q09OfUzDSq~CnfeE`L-Sgxavahi1nUeQk+l4)alx>B*2IpYM zQPu|igj0m9vqLFVd8 zJeqZ&c4)0~$leyGxtyQVEzx;KUCuRT9(oB9exXSSgLLqJP6(DUU+rMm?Va7gU^w<) zk1-Eb&ti((-&VWfO`=DTiIfiWeWFBLM1Zq|wk2|z6l1SF(Xo+XAi-#C+4Vz-XM6-j z;oK3TBCkceR4lj$_rual23NGUONMG_pH+ZS@rh4h5O6;HEmlj%WIR(_UjvHZFEE!c;G*FsUmx)tN z_0ErhT4N;iuuFr{q+SBD0Hl86ffbw*fMxQr5vd^0GF;%jHym4&g>Ln>Mj$Xj3N>TH z!3&$kubL1C)ub6F zkH`vvD4yVs@7*0c^5~yoIZr_N?Ne1a^7cqg--$?BUf3`+lNLfeW_$?opy8>E5wuy72DQb*1?96+hAEi_%0~H|;1J`SLCb7C2!i zv-rBGz6)~)Dn6<{+j+mX5kE}~&sGkT-CHq!jLC)LnG?qO(NAT^flYw-AuW^g5u$6< z{yRIiwMc7&9YE!Sg+kTzo4S0mngUgJv`a$b$l;

J$UV{&>!HMGwHuMWN_yy|Acj(ObcHrFcSi3v;8~LMdUv=?2#>el_ z$uoRMPk^QiwaVLjwF<6Yc@GyPYnUIp0yVIsQTIikHdPki`twJ-wd&rhauWHZ6}+R@ zKf$wB@QsT%t8(aYiueK_@nPf8b zlMInw*?e*X&;O*Z>kV1g8(i1@8~E>7)f*eKs!!^w-q2Ouy&+3J-@d`sMVNlCKI~Aq z1y1di&(}8oVm|-Hf5m&jCkzE&0U^z zBKzgX1YxDfZ7A%xCZ`6U=x`W!-xs#aiwD!MshQuw8th;Vc61GB&hPB#8tlmu2%5LQ zrwd?e**p6Dd*<=?%+v2J&Ra-{yN5?0)+FvT%+!2J_iC9M(_TI9uc%zx!isERMYgyi zf3vy871`1i*^(96(&MqEdtpo0V#}<>mRXCf#koM>%I?CiL#S_j8h(}KoM{XFDs|as z|Aa4U|5cbn{d#tu0F1}8GOR1@rE~|+GtU99XgDJNT)DP~Wn(#N56kw}l|9;H@YuOE z?(8k?r#XI9PSRdtCv9T~nUkyySrVPfNv5m+`Z@d<{;$O6sMkRTyQ?`{9PTU}&uAi? zs}l6^Y{-${*?}CX-~+}t9k<65#3adEE5$D{_>t~11UM*HXv`zujW;YE$1+KL27~6l zUh~~}2d-1R+{+`P5<_{CX({nmS6NCJIAaUp-dEbnZ8edo$^x(C;A@~y?rp!JrsDbr zkDc-4iJRWg%Wmk#G48EuBh8w@ijBML=$Q9;6|N4y$brTuj>yBS_@w{Fhj=@D%8taR zWas!)U5b<+qIP3eP$uGJ%UmJ` zLo6tu>AQ06)e!@b zD9?PP^V7n4Aq2LdIZ~1>*W0N%wZ<-?S+ZRTCrwLOrp}ZS(1^ zmjs(Joxt%>nyfD6s4J4~PbC}>rV3o7q{j)v8fc`X)Le36J*qQMHW}o*HKdUEcz-tT-x_S`;!j)WZ#1*`sU+QEC+Y_# zqrg8k(TT}xk%bbl(4R_XAFF>B%_bT)ScoV2%*m@?*PGKXF=scv6WjuyD1ir=`}wra z;ol#(fS|S62Q)QC%WOJ0VD1;kGR}@lu9aEcJ1ej=^PG)?gK-;7i(jb&1hh+f2p=_R zs)OQ9j&&H0NXNl;yu$(FuWa7o`DU0V=N=z=?(rKrGWe7ub4QLn_=rG@1U12(X`t{3 z2lCo$wd$+;_yrc_8=L==NAj)h|Fy|zVfz=G*s*VI^T+VPA7sq%)6et7RsYW>#}Ch| zIJfxT>Z|;rc~yRBUVT$e!o#aS)wlV#SNJn~Zz7k*2ma%$I0*mc3Xk^w-~J;xz?rh8*J?ym{a*YL=eVd%K~x zwtGXrZ2JbYHF)_}rw32J%EQAJ&BoG_N#j^1oGkWSk@0ej_@@B43G4g5jcfo{8y}2? zReKM3d+`82h4GzJ0CTJTcDVgGQY5jwaDZzS?Wq5M%y3fVn8lvgjpAtqR(VAVYJCmx zOwx>&5zZ?lgcdUK&M_jSK~Q_}=>$QnU-uADtjI76KU5UW08Pz~dT@4-?v}rnNcEJ}r!E-oT|PZK7NO?#4zyoN zzw!D2S2d%$!VV5<#A^CT*6E67Mr;LrPc^Z|R=d-fq5B2g2Zafqz^;7)r{f78?!Vc5 z0w?*-6B@QXAt(F^o`pGnMoz#JdbXc1XZs0r8lO;T*PJ}58T=ibJPeIBTzTwoLCvH{ z0MjB>rH5Cq%M)A|8+Bc6)OCFhQy#c(p5r?F0aJw|K*u0f+{B{X#G>3(i+7Wz;-)Uj zm*tXQHU{F$Y9GF=7rm*A^JQZkzO0MF@VJh*So$`Dc}HU@^9N&0^XAxU9813+mVr4O zq~n%=X$D|Jb0Z#h! Date: Wed, 29 Jul 2026 08:51:50 +0200 Subject: [PATCH 085/215] libc: update glibc crt0 code to 2.44 --- lib/libc/glibc/elf/elf.h | 8 +- lib/libc/glibc/include/libc-symbols.h | 3 +- lib/libc/glibc/sysdeps/aarch64/sysdep.h | 32 ++- lib/libc/glibc/sysdeps/arm/start.S | 27 +++ lib/libc/glibc/sysdeps/htl/libc-lockP.h | 14 ++ lib/libc/glibc/sysdeps/loongarch/start.S | 26 +- lib/libc/glibc/sysdeps/loongarch/sys/asm.h | 104 ++++++++ lib/libc/glibc/sysdeps/loongarch/sysdep.h | 94 ++++++++ lib/libc/glibc/sysdeps/mach/libc-lock.h | 20 +- .../sysdeps/s390/{s390-64 => }/start-2.33.S | 0 .../glibc/sysdeps/s390/{s390-64 => }/start.S | 0 .../glibc/sysdeps/s390/{s390-64 => }/sysdep.h | 0 .../sysdeps/unix/sysv/linux/kernel-features.h | 7 +- .../unix/sysv/linux/loongarch/sysdep.h | 31 ++- .../unix/sysv/linux/s390/bits/typesizes.h | 36 ++- .../unix/sysv/linux/s390/kernel-features.h | 3 - .../unix/sysv/linux/s390/s390-64/sysdep.h | 178 -------------- .../sysdeps/unix/sysv/linux/s390/sysdep.h | 223 +++++++++++++++--- .../sysdeps/unix/sysv/linux/s390/xstatver.h | 21 +- src/libs/glibc.zig | 4 +- 20 files changed, 541 insertions(+), 290 deletions(-) create mode 100644 lib/libc/glibc/sysdeps/loongarch/sys/asm.h create mode 100644 lib/libc/glibc/sysdeps/loongarch/sysdep.h rename lib/libc/glibc/sysdeps/s390/{s390-64 => }/start-2.33.S (100%) rename lib/libc/glibc/sysdeps/s390/{s390-64 => }/start.S (100%) rename lib/libc/glibc/sysdeps/s390/{s390-64 => }/sysdep.h (100%) delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h diff --git a/lib/libc/glibc/elf/elf.h b/lib/libc/glibc/elf/elf.h index 46a01281cb0fb5322d5124f0443c11dea4d5b721..b482fcfb64890752fc1aa4e9d208a7b94f022d38 100644 --- a/lib/libc/glibc/elf/elf.h +++ b/lib/libc/glibc/elf/elf.h @@ -798,7 +798,8 @@ typedef struct #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ #define NT_X86_SHSTK 0x204 /* x86 SHSTK state */ #define NT_X86_XSAVE_LAYOUT 0x205 /* XSAVE layout description. */ -#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ +#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves. This was + used in now removed s390-32 arch. */ #define NT_S390_TIMER 0x301 /* s390 timer register */ #define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ @@ -846,6 +847,7 @@ typedef struct #define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */ #define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged address control */ +#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */ #define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */ #define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers. */ @@ -3470,7 +3472,9 @@ enum /* Valid values for the e_flags field. */ -#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ +#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. + This was used in now removed s390-32 + arch. */ /* Additional s390 relocs */ diff --git a/lib/libc/glibc/include/libc-symbols.h b/lib/libc/glibc/include/libc-symbols.h index bebfc67cec098bf106bb9231bd3ff47e8f85d31f..a6aef303a22fa1a23c2a8f88f33451c803476e38 100644 --- a/lib/libc/glibc/include/libc-symbols.h +++ b/lib/libc/glibc/include/libc-symbols.h @@ -113,6 +113,7 @@ #define HAVE_LIBINTL_H 1 #define HAVE_WCTYPE_H 1 #define HAVE_ISWCTYPE 1 +#define HAVE_MEMPCPY 1 #define ENABLE_NLS 1 /* The symbols in all the user (non-_) macros are C symbols. */ @@ -682,7 +683,7 @@ for linking") /* Helper / base macros for indirect function symbols. */ #define __ifunc_resolver(type_name, name, expr, init, classifier, ...) \ - classifier inhibit_stack_protector \ + classifier \ __typeof (type_name) *name##_ifunc (__VA_ARGS__) \ { \ init (); \ diff --git a/lib/libc/glibc/sysdeps/aarch64/sysdep.h b/lib/libc/glibc/sysdeps/aarch64/sysdep.h index da4b7f3fd32c4fbd62ce777d1857baeda279dcbb..77e6564d97bb5473bc915dde142522f7ee938914 100644 --- a/lib/libc/glibc/sysdeps/aarch64/sysdep.h +++ b/lib/libc/glibc/sysdeps/aarch64/sysdep.h @@ -43,7 +43,6 @@ #define FEATURE_1_PAC 2 #define FEATURE_1_GCS 4 -/* Add a NT_GNU_PROPERTY_TYPE_0 note. */ #define GNU_PROPERTY(type, value) \ .section .note.gnu.property, "a"; \ .p2align 3; \ @@ -57,9 +56,34 @@ .word 0; \ .text -/* Add GNU property note with the supported features to all asm code - where sysdep.h is included. */ -GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI|FEATURE_1_PAC|FEATURE_1_GCS) +#ifdef __ARM_BUILDATTR64_FV +/* Add AArch64 feature bits build attributes. */ +# define FEATURE_1_AND_MARK(value) \ + .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128; \ + .if ((value) & FEATURE_1_BTI); \ + .aeabi_attribute Tag_Feature_BTI, 1; \ + .else; \ + .aeabi_attribute Tag_Feature_BTI, 0; \ + .endif; \ + .if ((value) & FEATURE_1_GCS); \ + .aeabi_attribute Tag_Feature_GCS, 1; \ + .else; \ + .aeabi_attribute Tag_Feature_GCS, 0; \ + .endif; \ + .if ((value) & FEATURE_1_PAC); \ + .aeabi_attribute Tag_Feature_PAC, 1; \ + .else; \ + .aeabi_attribute Tag_Feature_PAC, 0; \ + .endif; \ + .text +#else +/* Add a NT_GNU_PROPERTY_TYPE_0 note. */ +# define FEATURE_1_AND_MARK(value) GNU_PROPERTY (FEATURE_1_AND, value) +#endif /* __ARM_BUILDATTR64_FV */ + +/* Add marking with the supported features to all asm code where sysdep.h + is included. */ +FEATURE_1_AND_MARK (FEATURE_1_BTI | FEATURE_1_PAC | FEATURE_1_GCS) /* Define an entry point visible from C. */ #define ENTRY(name) \ diff --git a/lib/libc/glibc/sysdeps/arm/start.S b/lib/libc/glibc/sysdeps/arm/start.S index a7e62b39346d18be9d46f64048b092e7c873b068..6b154dc7d33e3450b94991e9d827a3edf85acc9f 100644 --- a/lib/libc/glibc/sysdeps/arm/start.S +++ b/lib/libc/glibc/sysdeps/arm/start.S @@ -90,6 +90,7 @@ _start: push { a1 } #ifdef PIC +# ifdef SHARED ldr sl, .L_GOT adr a4, .L_GOT add sl, sl, a4 @@ -103,6 +104,16 @@ _start: /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ /* Let the libc call main and exit with its return code. */ bl __libc_start_main(PLT) +# else + ldr a1, .L_main_rel /* Load the relative offset of __wrap_main. */ + adr a4, .L_main_rel /* Load the actual runtime address of the label. */ + add a1, a4, a1 /* Add them together to get the absolute address. */ + + mov a4, #0 /* Used to be init. */ + push { a4 } /* Used to be fini. */ + + bl __libc_start_main +# endif /* ifdef SHARED */ #else mov a4, #0 /* Used to init. */ @@ -119,14 +130,30 @@ _start: #ifdef PIC .align 2 +# ifdef SHARED .L_GOT: .word _GLOBAL_OFFSET_TABLE_ - .L_GOT .word main(GOT) +# else +.L_main_rel: + .word __wrap_main - .L_main_rel +# endif #endif .cantunwind .fnend +#if defined PIC && !defined SHARED +/* When main is not defined in the executable but in a shared library then + a wrapper is needed, because crt1.o and rcrt1.o share this code and the + latter (static PIE) must avoid GOT relocations before __libc_start_main + is called. The branch to main is turned into a PLT entry by every linker, + unlike a REL32 data relocation against main. */ + .type __wrap_main, %function +__wrap_main: + b main +#endif + /* Define a symbol for the first piece of initialized data. */ .data .globl __data_start diff --git a/lib/libc/glibc/sysdeps/htl/libc-lockP.h b/lib/libc/glibc/sysdeps/htl/libc-lockP.h index a88eea4344004d7bcacdcd6bb827547ab9a41026..e20e40f2540f0d23b4215910637196cb0ad91959 100644 --- a/lib/libc/glibc/sysdeps/htl/libc-lockP.h +++ b/lib/libc/glibc/sysdeps/htl/libc-lockP.h @@ -21,6 +21,20 @@ #include +typedef pthread_rwlock_t __libc_rwlock_t; + +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; +#define __libc_rwlock_init(NAME) __pthread_rwlock_init (&(NAME), NULL) +#define __libc_rwlock_fini(NAME) ((void) 0) +#define __libc_rwlock_rdlock(NAME) __pthread_rwlock_rdlock (&(NAME)) +#define __libc_rwlock_wrlock(NAME) __pthread_rwlock_wrlock (&(NAME)) +#define __libc_rwlock_tryrdlock(NAME) __pthread_rwlock_tryrdlock (&(NAME)) +#define __libc_rwlock_trywrlock(NAME) __pthread_rwlock_trywrlock (&(NAME)) +#define __libc_rwlock_unlock(NAME) __pthread_rwlock_unlock (&(NAME)) + /* If we check for a weakly referenced symbol and then perform a normal jump to it te code generated for some platforms in case of PIC is unnecessarily slow. What would happen is that the function diff --git a/lib/libc/glibc/sysdeps/loongarch/start.S b/lib/libc/glibc/sysdeps/loongarch/start.S index 72452f5307ef430c06fd5852190c68d5f1295366..7be47a034df972d645cd6bd4a09afa0c450f5ca2 100644 --- a/lib/libc/glibc/sysdeps/loongarch/start.S +++ b/lib/libc/glibc/sysdeps/loongarch/start.S @@ -36,6 +36,7 @@ #define __ASSEMBLY__ 1 #include #include +#include /* The entry point's job is to call __libc_start_main. Per the ABI, a0 contains the address of a function to be passed to atexit. @@ -57,23 +58,32 @@ ENTRY (ENTRY_POINT) /* Terminate call stack by noting ra is undefined. Use a dummy .cfi_label to force starting the FDE. */ .cfi_label .Ldummy - cfi_undefined (1) + cfi_undefined (1) or a5, a0, zero /* rtld_fini */ - la.pcrel a0, t0, main +#if defined PIC && !defined SHARED + /* Avoid relocation in static PIE since _start is called before it + is relocated. */ + la.pcrel a0, __wrap_main +#else + LA_GOT (a0, main) +#endif + REG_L a1, sp, 0 ADDI a2, sp, SZREG - /* Adjust $sp for 16-aligned */ - BSTRINS sp, zero, 3, 0 + /* Adjust $sp for 16-bytes aligned */ + REG_ALIGN_ASM (sp, 4) move a3, zero /* used to be init */ move a4, zero /* used to be fini */ or a6, sp, zero /* stack_end */ - la.pcrel ra, t0, __libc_start_main - jirl ra, ra, 0 + CALL (__libc_start_main) + CALL (abort) - la.pcrel ra, t0, abort - jirl ra, ra, 0 +#if defined PIC && !defined SHARED +__wrap_main: + TAIL (main) +#endif END (ENTRY_POINT) diff --git a/lib/libc/glibc/sysdeps/loongarch/sys/asm.h b/lib/libc/glibc/sysdeps/loongarch/sys/asm.h new file mode 100644 index 0000000000000000000000000000000000000000..de44aacfa411fc9f6be2ddcd64acea0a75117cea --- /dev/null +++ b/lib/libc/glibc/sysdeps/loongarch/sys/asm.h @@ -0,0 +1,104 @@ +/* Miscellaneous macros. + Copyright (C) 2022-2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _SYS_ASM_H +#define _SYS_ASM_H + +#include +#include + +/* Macros to handle different pointer/register sizes for 32/64-bit code. */ +#if __loongarch_grlen == 64 +#define SZREG 8 +#define REG_L ld.d +#define REG_S st.d +#define SRLI srli.d +#define SLLI slli.d +#define ADDI addi.d +#define ADD add.d +#define SUB sub.d +#define LI li.d +#define BSTRINS bstrins.d + +#elif __loongarch_grlen == 32 + +#define SZREG 4 +#define REG_L ld.w +#define REG_S st.w +#define SRLI srli.w +#define SLLI slli.w +#define ADDI addi.w +#define ADD add.w +#define SUB sub.w +#define LI li.w +#define BSTRINS bstrins.w + +#else +#error __loongarch_grlen must equal 32 or 64 +#endif + +#if __loongarch_frlen == 64 + #define SZFREG 8 + #define FREG_L fld.d + #define FREG_S fst.d +#elif __loongarch_frlen == 32 + #define SZFREG 4 + #define FREG_L fld.s + #define FREG_S fst.s +#endif + +#define SZVREG 16 +#define SZXREG 32 + +/* Declare leaf routine. + The usage of macro LEAF/ENTRY is as follows: + 1. LEAF(fcn) -- the align value of fcn is .align 3 (default value) + 2. LEAF(fcn, 6) -- the align value of fcn is .align 6 +*/ +#define LEAF_IMPL(symbol, aln, ...) \ + .text; \ + .globl symbol; \ + .align aln; \ + .type symbol, @function; \ +symbol: \ + cfi_startproc; + + +#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3) +#define ENTRY(...) LEAF(__VA_ARGS__) + +#define LEAF_NO_ALIGN(symbol) \ + .text; \ + .globl symbol; \ + .type symbol, @function; \ +symbol: \ + cfi_startproc; + +#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol) + + +/* Mark end of function. */ +#undef END +#define END(function) \ + cfi_endproc; \ + .size function, .- function; + +/* Stack alignment. */ +#define ALMASK ~15 + +#endif /* sys/asm.h */ diff --git a/lib/libc/glibc/sysdeps/loongarch/sysdep.h b/lib/libc/glibc/sysdeps/loongarch/sysdep.h new file mode 100644 index 0000000000000000000000000000000000000000..d5fc0b08633b383c8bbcb9e0213c214d9a141c3b --- /dev/null +++ b/lib/libc/glibc/sysdeps/loongarch/sysdep.h @@ -0,0 +1,94 @@ +/* Macros for LoongArch. + Copyright (C) 2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _LOONGARCH_SYSDEP_H +#define _LOONGARCH_SYSDEP_H + +#if __loongarch_grlen == 64 + +#define PTRLOG 3 +/* Align reg to 2^n. Used in C. */ +#define REG_ALIGN_C(reg, n) \ + "bstrins.d\t" __STRING(reg) ", $zero, (" __STRING(n) "-1), 0" + +#elif __loongarch_grlen == 32 + +#define PTRLOG 2 +#define REG_ALIGN_C(reg, n) \ + "srli.w\t" __STRING(reg)", " __STRING(reg)", " __STRING(n) "\n\t" \ + "slli.w\t" __STRING(reg)", " __STRING(reg)", " __STRING(n) + +#else +#error __loongarch_grlen must equal 32 or 64 +#endif + +#ifdef __ASSEMBLER__ + +/* Stack alignment bytes. */ +#define STACK_ALIGN 16 + +/* Macros to handle different pointer/register sizes for 32/64-bit code. */ +#if __loongarch_grlen == 64 +#define SRAI srai.d + +/* Align reg to 2^n. Used in assembly. */ +#define REG_ALIGN_ASM(reg, n) bstrins.d reg, zero, (n-1), 0 + +#define LOAD_LOCAL(reg, sym) \ + pcalau12i reg, %pc_hi20(sym); \ + ld.d reg, reg, %pc_lo12(sym); + +#define LOAD_GLOBAL(reg, sym) \ + la.got reg, sym; \ + ld.d reg, reg, 0; + +#define LA_GOT(reg, sym) la.got reg, t0, sym + +#define CALL(sym) call36 sym +#define TAIL(sym) tail36 t0, sym + +#elif __loongarch_grlen == 32 /* __loongarch_grlen == 64 */ + +#define SRAI srai.w + +/* LA32R not have bstrins.w, use srli.w and slli.w on both LA32S and LA32R. */ +#define REG_ALIGN_ASM(reg, n) \ + srli.w reg, reg, n; \ + slli.w reg, reg, n; + +#define LOAD_LOCAL(reg, sym) \ + 1: pcaddu12i reg, %pcadd_hi20(sym); \ + ld.w reg, reg, %pcadd_lo12(1b); + +#define LOAD_GLOBAL(reg, sym) \ + 1: pcaddu12i reg, %got_pcadd_hi20(sym); \ + ld.w reg, reg, %pcadd_lo12(1b); \ + ld.w reg, reg, 0; + +#define LA_GOT(reg, sym) la.got reg, sym + +#define CALL(sym) call30 sym +#define TAIL(sym) tail30 t0, sym + +#else /* __loongarch_grlen == 64 */ +#error __loongarch_grlen must equal 32 or 64 +#endif /* __loongarch_grlen == 64 */ + +#endif /* __ASSEMBLER__ */ + +#endif /* _LOONGARCH_SYSDEP_H */ diff --git a/lib/libc/glibc/sysdeps/mach/libc-lock.h b/lib/libc/glibc/sysdeps/mach/libc-lock.h index 236a24ad807ea292bb25258d64ffb5658f5ddcf5..c5c67ccf9daa2fc5a02b63321f9fcdcf4617ec59 100644 --- a/lib/libc/glibc/sysdeps/mach/libc-lock.h +++ b/lib/libc/glibc/sysdeps/mach/libc-lock.h @@ -145,16 +145,16 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; #define __rtld_lock_unlock_recursive(NAME) \ __libc_lock_unlock_recursive (NAME) -/* XXX for now */ -#define __libc_rwlock_define __libc_lock_define -#define __libc_rwlock_define_initialized __libc_lock_define_initialized -#define __libc_rwlock_init __libc_lock_init -#define __libc_rwlock_fini __libc_lock_fini -#define __libc_rwlock_rdlock __libc_lock_lock -#define __libc_rwlock_wrlock __libc_lock_lock -#define __libc_rwlock_tryrdlock __libc_lock_trylock -#define __libc_rwlock_trywrlock __libc_lock_trylock -#define __libc_rwlock_unlock __libc_lock_unlock +/* XXX for now, waiting for a futex-based pthread_rwlock implementation */ +#define __mach_rwlock_define __libc_lock_define +#define __mach_rwlock_define_initialized __libc_lock_define_initialized +#define __mach_rwlock_init __libc_lock_init +#define __mach_rwlock_fini __libc_lock_fini +#define __mach_rwlock_rdlock __libc_lock_lock +#define __mach_rwlock_wrlock __libc_lock_lock +#define __mach_rwlock_tryrdlock __libc_lock_trylock +#define __mach_rwlock_trywrlock __libc_lock_trylock +#define __mach_rwlock_unlock __libc_lock_unlock struct __libc_cleanup_frame { diff --git a/lib/libc/glibc/sysdeps/s390/s390-64/start-2.33.S b/lib/libc/glibc/sysdeps/s390/start-2.33.S similarity index 100% rename from lib/libc/glibc/sysdeps/s390/s390-64/start-2.33.S rename to lib/libc/glibc/sysdeps/s390/start-2.33.S diff --git a/lib/libc/glibc/sysdeps/s390/s390-64/start.S b/lib/libc/glibc/sysdeps/s390/start.S similarity index 100% rename from lib/libc/glibc/sysdeps/s390/s390-64/start.S rename to lib/libc/glibc/sysdeps/s390/start.S diff --git a/lib/libc/glibc/sysdeps/s390/s390-64/sysdep.h b/lib/libc/glibc/sysdeps/s390/sysdep.h similarity index 100% rename from lib/libc/glibc/sysdeps/s390/s390-64/sysdep.h rename to lib/libc/glibc/sysdeps/s390/sysdep.h diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/kernel-features.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/kernel-features.h index 42318b0a6fe51b9f1c6a61ba9b298904c16493d2..d41bda5112cc96e254232ba99881bfac21be77bb 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/kernel-features.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/kernel-features.h @@ -155,7 +155,7 @@ similar to kernel: - __ASSUME_CLONE_BACKWARDS: for variant 1. - - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390). + - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390x). - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze). - __ASSUME_CLONE_DEFAULT: for variant 4. */ @@ -266,4 +266,9 @@ /* zig patch: don't assume kernel version */ #define __ASSUME_MSEAL 0 +/* The PIDFD_GET_INFO ioctl was introduced across all architectures in Linux + 6.13. */ +/* zig patch: don't assume kernel version */ +#define __ASSUME_PIDFD_GET_INFO 0 + #endif /* kernel-features.h */ diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h index ac5b36f8c02218289d06f1f9be3dc40b42952cc1..eaa9e52575b139c33fa4f929e18a83b28d3d4d28 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h @@ -19,6 +19,7 @@ #ifndef _LINUX_LOONGARCH_SYSDEP_H #define _LINUX_LOONGARCH_SYSDEP_H 1 +#include #include #include #include @@ -34,9 +35,9 @@ #undef PSEUDO #define PSEUDO(name, syscall_name, args) \ ENTRY (name); \ - li.d a7, SYS_ify (syscall_name); \ + LI a7, SYS_ify (syscall_name); \ syscall 0; \ - li.d a7, -4096; \ + LI a7, -4096; \ bltu a7, a0, .Lsyscall_error##name; #undef PSEUDO_END @@ -52,16 +53,16 @@ .Lsyscall_error##name : la t0, rtld_errno; \ sub.w a0, zero, a0; \ st.w a0, t0, 0; \ - li.d a0, -1; + LI a0, -1; #else #define SYSCALL_ERROR_HANDLER(name) \ .Lsyscall_error##name : la.tls.ie t0, errno; \ - add.d t0, tp, t0; \ + ADD t0, tp, t0; \ sub.w a0, zero, a0; \ st.w a0, t0, 0; \ - li.d a0, -1; + LI a0, -1; #endif #else @@ -74,7 +75,7 @@ #undef PSEUDO_NEORRNO #define PSEUDO_NOERRNO(name, syscall_name, args) \ ENTRY (name); \ - li.d a7, SYS_ify (syscall_name); \ + LI a7, SYS_ify (syscall_name); \ syscall 0; #undef PSEUDO_END_NOERRNO @@ -85,11 +86,17 @@ /* Performs a system call, returning the error code. */ #undef PSEUDO_ERRVAL +#if __loongarch_grlen == 64 #define PSEUDO_ERRVAL(name, syscall_name, args) \ PSEUDO_NOERRNO (name, syscall_name, args); \ slli.d a0, a0, 32; \ srai.d a0, a0, 32; /* sign_ext */ \ sub.d a0, zero, a0; +#else +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + PSEUDO_NOERRNO (name, syscall_name, args); \ + sub.w a0, zero, a0; +#endif #undef PSEUDO_END_ERRVAL #define PSEUDO_END_ERRVAL(name) END (name); @@ -109,6 +116,18 @@ #undef SYS_ify #define SYS_ify(syscall_name) __NR_##syscall_name +#if __WORDSIZE == 32 +/* Workarounds for generic code needing to handle 64-bit time_t. */ +#define __NR_clock_getres __NR_clock_getres_time64 +#define __NR_futex __NR_futex_time64 +#define __NR_ppoll __NR_ppoll_time64 +#define __NR_pselect6 __NR_pselect6_time64 +#define __NR_recvmmsg __NR_recvmmsg_time64 +#define __NR_rt_sigtimedwait __NR_rt_sigtimedwait_time64 +#define __NR_semtimedop __NR_semtimedop_time64 +#define __NR_utimensat __NR_utimensat_time64 +#endif /* __WORDSIZE == 32 */ + #ifndef __ASSEMBLER__ #define VDSO_NAME "LINUX_5.10" diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h index 826a1e425c1a2b3b1ee712643d53284412275bfa..6e2be2270f3ef2352418c9ca49af32ecd9e1f9ca 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/bits/typesizes.h @@ -57,42 +57,34 @@ #define __TIMER_T_TYPE void * #define __BLKSIZE_T_TYPE __SLONGWORD_TYPE #define __FSID_T_TYPE struct { int __val[2]; } -#if defined __GNUC__ && __GNUC__ <= 2 -/* Compatibility with g++ 2.95.x. */ -#define __SSIZE_T_TYPE __SWORD_TYPE -#else -/* size_t is unsigned long int on s390 -m31. */ -#define __SSIZE_T_TYPE __SLONGWORD_TYPE -#endif + +/* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with + g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was + unsigned long int on s390-32. + Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the + generic version as both types result in long int. */ +#define __SSIZE_T_TYPE __SWORD_TYPE + #define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE #define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE -#define __CPU_MASK_TYPE __ULONGWORD_TYPE +#define __CPU_MASK_TYPE __ULONGWORD_TYPE -#ifdef __s390x__ /* Tell the libc code that off_t and off64_t are actually the same type for all ABI purposes, even if possibly expressed as different base types for C type-checking purposes. */ -# define __OFF_T_MATCHES_OFF64_T 1 +#define __OFF_T_MATCHES_OFF64_T 1 /* Same for ino_t and ino64_t. */ -# define __INO_T_MATCHES_INO64_T 1 +#define __INO_T_MATCHES_INO64_T 1 /* And for __rlim_t and __rlim64_t. */ -# define __RLIM_T_MATCHES_RLIM64_T 1 +#define __RLIM_T_MATCHES_RLIM64_T 1 /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */ -# define __STATFS_MATCHES_STATFS64 1 +#define __STATFS_MATCHES_STATFS64 1 /* And for getitimer, setitimer and rusage */ -# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 -#else -# define __RLIM_T_MATCHES_RLIM64_T 0 - -# define __STATFS_MATCHES_STATFS64 0 - -/* And for getitimer, setitimer and rusage */ -# define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0 -#endif +#define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 /* Number of descriptors that can fit in an `fd_set'. */ #define __FD_SETSIZE 1024 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h index a955c18738ad557e51a261b279eb2e3111870924..d7af29285fc538b2deda44f9aab98e5fcb60fef1 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h @@ -47,9 +47,6 @@ # undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS # undef __ASSUME_SYSVIPC_DEFAULT_IPC_64 #endif -#ifndef __s390x__ -# define __ASSUME_SYSVIPC_BROKEN_MODE_T -#endif #undef __ASSUME_CLONE_DEFAULT #define __ASSUME_CLONE_BACKWARDS2 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h deleted file mode 100644 index 9c9e2a271f57c5ce5d2efef9fc23c36ea55da6ac..0000000000000000000000000000000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Assembler macros for 64 bit S/390. - Copyright (C) 2001-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _LINUX_S390_SYSDEP_H -#define _LINUX_S390_SYSDEP_H - -#include -#include -#include -#include -#include /* For RTLD_PRIVATE_ERRNO. */ -#include - -/* For Linux we can use the system call table in the header file - /usr/include/asm/unistd.h - of the kernel. But these symbols do not follow the SYS_* syntax - so we have to redefine the `SYS_ify' macro here. */ -/* In newer 2.1 kernels __NR_syscall is missing so we define it here. */ -#define __NR_syscall 0 - -#undef SYS_ify -#define SYS_ify(syscall_name) __NR_##syscall_name - -#ifdef __ASSEMBLER__ - -/* Linux uses a negative return value to indicate syscall errors, unlike - most Unices, which use the condition codes' carry flag. - - Since version 2.1 the return value of a system call might be negative - even if the call succeeded. E.g., the `lseek' system call might return - a large offset. Therefore we must not anymore test for < 0, but test - for a real error by making sure the value in gpr2 is a real error - number. Linus said he will make sure that no syscall returns a value - in -1 .. -4095 as a valid result so we can safely test with -4095. */ - -#undef PSEUDO -#define PSEUDO(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args); \ - lghi %r4,-4095 ; \ - clgr %r2,%r4 ; \ - jgnl SYSCALL_ERROR_LABEL - -#undef PSEUDO_END -#define PSEUDO_END(name) \ - SYSCALL_ERROR_HANDLER; \ - END (name) - -#undef PSEUDO_NOERRNO -#define PSEUDO_NOERRNO(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args) - -#undef PSEUDO_END_NOERRNO -#define PSEUDO_END_NOERRNO(name) \ - SYSCALL_ERROR_HANDLER; \ - END (name) - -#undef PSEUDO_ERRVAL -#define PSEUDO_ERRVAL(name, syscall_name, args) \ - .text; \ - ENTRY (name) \ - DO_CALL (syscall_name, args); \ - lcgr %r2,%r2 - -#undef PSEUDO_END_ERRVAL -#define PSEUDO_END_ERRVAL(name) \ - SYSCALL_ERROR_HANDLER; \ - END (name) - -#undef SYSCALL_ERROR_LABEL -#ifndef PIC -# undef SYSCALL_ERROR_LABEL -# define SYSCALL_ERROR_LABEL syscall_error -# define SYSCALL_ERROR_HANDLER -#else -# if RTLD_PRIVATE_ERRNO -# undef SYSCALL_ERROR_LABEL -# define SYSCALL_ERROR_LABEL 0f -# define SYSCALL_ERROR_HANDLER \ -0: larl %r1,rtld_errno; \ - lcr %r2,%r2; \ - st %r2,0(%r1); \ - lghi %r2,-1; \ - br %r14 -# elif defined _LIBC_REENTRANT -# if IS_IN (libc) -# define SYSCALL_ERROR_ERRNO __libc_errno -# else -# define SYSCALL_ERROR_ERRNO errno -# endif -# undef SYSCALL_ERROR_LABEL -# define SYSCALL_ERROR_LABEL 0f -# define SYSCALL_ERROR_HANDLER \ -0: lcr %r0,%r2; \ - larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \ - lg %r1,0(%r1); \ - ear %r2,%a0; \ - sllg %r2,%r2,32; \ - ear %r2,%a1; \ - st %r0,0(%r1,%r2); \ - lghi %r2,-1; \ - br %r14 -# else -# undef SYSCALL_ERROR_LABEL -# define SYSCALL_ERROR_LABEL 0f -# define SYSCALL_ERROR_HANDLER \ -0: larl %r1,_GLOBAL_OFFSET_TABLE_; \ - lg %r1,errno@GOT(%r1); \ - lcr %r2,%r2; \ - st %r2,0(%r1); \ - lghi %r2,-1; \ - br %r14 -# endif /* _LIBC_REENTRANT */ -#endif /* PIC */ - -/* Linux takes system call arguments in registers: - - syscall number 1 call-clobbered - arg 1 2 call-clobbered - arg 2 3 call-clobbered - arg 3 4 call-clobbered - arg 4 5 call-clobbered - arg 5 6 call-saved - arg 6 7 call-saved - - (Of course a function with say 3 arguments does not have entries for - arguments 4 and 5.) - For system calls with 6 parameters a stack operation is required - to load the 6th parameter to register 7. Call saved register 7 is - moved to register 0 and back to avoid an additional stack frame. - */ - -#define DO_CALL(syscall, args) \ - .if args > 5; \ - lgr %r0,%r7; \ - lg %r7,160(%r15); \ - .endif; \ - lghi %r1,SYS_ify (syscall); \ - svc 0; \ - .if args > 5; \ - lgr %r7,%r0; \ - .endif - -#define ret \ - br 14 - -#define ret_NOERRNO \ - br 14 - -#define ret_ERRVAL \ - br 14 - -#else - -# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL -# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 - -#endif /* __ASSEMBLER__ */ - -#endif /* _LINUX_S390_SYSDEP_H */ diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h index ee2d92edff1f0ee2fb8e0a25217e35dccbd0ff30..42fb8aa4692be8cd884dc9cb076b7c62412c03f0 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h @@ -1,5 +1,5 @@ -/* Syscall definitions, Linux s390 version. - Copyright (C) 2019-2026 Free Software Foundation, Inc. +/* Assembler macros for 64 bit S/390. + Copyright (C) 2001-2026 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -14,15 +14,163 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see - . */ + . */ -#ifndef __ASSEMBLY__ +#ifndef _LINUX_S390_SYSDEP_H +#define _LINUX_S390_SYSDEP_H + +#include +#include +#include +#include /* For RTLD_PRIVATE_ERRNO. */ +#include + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +/* In newer 2.1 kernels __NR_syscall is missing so we define it here. */ +#define __NR_syscall 0 #undef SYS_ify #define SYS_ify(syscall_name) __NR_##syscall_name -#undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(no, nr, args...) \ +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, unlike + most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be negative + even if the call succeeded. E.g., the `lseek' system call might return + a large offset. Therefore we must not anymore test for < 0, but test + for a real error by making sure the value in gpr2 is a real error + number. Linus said he will make sure that no syscall returns a value + in -1 .. -4095 as a valid result so we can safely test with -4095. */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + lghi %r4,-4095 ; \ + clgr %r2,%r4 ; \ + jgnl SYSCALL_ERROR_LABEL + +# undef PSEUDO_END +# define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER; \ + END (name) + +# undef PSEUDO_NOERRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args) + +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ + SYSCALL_ERROR_HANDLER; \ + END (name) + +# undef PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + lcgr %r2,%r2 + +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ + SYSCALL_ERROR_HANDLER; \ + END (name) + +# undef SYSCALL_ERROR_LABEL +# ifndef PIC +# undef SYSCALL_ERROR_LABEL +# define SYSCALL_ERROR_LABEL syscall_error +# define SYSCALL_ERROR_HANDLER +# else +# if RTLD_PRIVATE_ERRNO +# undef SYSCALL_ERROR_LABEL +# define SYSCALL_ERROR_LABEL 0f +# define SYSCALL_ERROR_HANDLER \ +0: larl %r1,rtld_errno; \ + lcr %r2,%r2; \ + st %r2,0(%r1); \ + lghi %r2,-1; \ + br %r14 +# elif defined _LIBC_REENTRANT +# if IS_IN (libc) +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# undef SYSCALL_ERROR_LABEL +# define SYSCALL_ERROR_LABEL 0f +# define SYSCALL_ERROR_HANDLER \ +0: lcr %r0,%r2; \ + larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \ + lg %r1,0(%r1); \ + ear %r2,%a0; \ + sllg %r2,%r2,32; \ + ear %r2,%a1; \ + st %r0,0(%r1,%r2); \ + lghi %r2,-1; \ + br %r14 +# else +# undef SYSCALL_ERROR_LABEL +# define SYSCALL_ERROR_LABEL 0f +# define SYSCALL_ERROR_HANDLER \ +0: larl %r1,_GLOBAL_OFFSET_TABLE_; \ + lg %r1,errno@GOT(%r1); \ + lcr %r2,%r2; \ + st %r2,0(%r1); \ + lghi %r2,-1; \ + br %r14 +# endif /* _LIBC_REENTRANT */ +# endif /* PIC */ + +/* Linux takes system call arguments in registers: + + syscall number 1 call-clobbered + arg 1 2 call-clobbered + arg 2 3 call-clobbered + arg 3 4 call-clobbered + arg 4 5 call-clobbered + arg 5 6 call-saved + arg 6 7 call-saved + + (Of course a function with say 3 arguments does not have entries for + arguments 4 and 5.) + For system calls with 6 parameters a stack operation is required + to load the 6th parameter to register 7. Call saved register 7 is + moved to register 0 and back to avoid an additional stack frame. + */ + +# define DO_CALL(syscall, args) \ + .if args > 5; \ + lgr %r0,%r7; \ + lg %r7,160(%r15); \ + .endif; \ + lghi %r1,SYS_ify (syscall); \ + svc 0; \ + .if args > 5; \ + lgr %r7,%r0; \ + .endif + +# define ret \ + br 14 + +# define ret_NOERRNO \ + br 14 + +# define ret_ERRVAL \ + br 14 + +#else /* not __ASSEMBLER__ */ + +# undef INTERNAL_SYSCALL_NCS +# define INTERNAL_SYSCALL_NCS(no, nr, args...) \ ({ \ DECLARGS_##nr(args) \ register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \ @@ -34,51 +182,52 @@ : "memory" ); \ _ret; }) -#undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, nr, args...) \ +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, nr, args...) \ INTERNAL_SYSCALL_NCS(__NR_##name, nr, args) -#define DECLARGS_0() -#define DECLARGS_1(arg1) \ +# define DECLARGS_0() +# define DECLARGS_1(arg1) \ register unsigned long int gpr2 __asm__ ("2") = (unsigned long int)(arg1); -#define DECLARGS_2(arg1, arg2) \ +# define DECLARGS_2(arg1, arg2) \ DECLARGS_1(arg1) \ register unsigned long int gpr3 __asm__ ("3") = (unsigned long int)(arg2); -#define DECLARGS_3(arg1, arg2, arg3) \ +# define DECLARGS_3(arg1, arg2, arg3) \ DECLARGS_2(arg1, arg2) \ register unsigned long int gpr4 __asm__ ("4") = (unsigned long int)(arg3); -#define DECLARGS_4(arg1, arg2, arg3, arg4) \ +# define DECLARGS_4(arg1, arg2, arg3, arg4) \ DECLARGS_3(arg1, arg2, arg3) \ register unsigned long int gpr5 __asm__ ("5") = (unsigned long int)(arg4); -#define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \ +# define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \ DECLARGS_4(arg1, arg2, arg3, arg4) \ register unsigned long int gpr6 __asm__ ("6") = (unsigned long int)(arg5); -#define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ +# define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \ register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6); -#define ASMFMT_0 -#define ASMFMT_1 , "0" (gpr2) -#define ASMFMT_2 , "0" (gpr2), "d" (gpr3) -#define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4) -#define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5) -#define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6) -#define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7) +# define ASMFMT_0 +# define ASMFMT_1 , "0" (gpr2) +# define ASMFMT_2 , "0" (gpr2), "d" (gpr3) +# define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4) +# define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5) +# define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6) +# define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7) -#define VDSO_NAME "LINUX_2.6.29" -#define VDSO_HASH 123718585 +# define VDSO_NAME "LINUX_2.6.29" +# define VDSO_HASH 123718585 /* List of system calls which are supported as vsyscalls. */ -#ifdef __s390x__ -#define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres" -#define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime" -#define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom" -#else -#define HAVE_CLOCK_GETRES_VSYSCALL "__kernel_clock_getres" -#define HAVE_CLOCK_GETTIME_VSYSCALL "__kernel_clock_gettime" -#endif -#define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday" -#define HAVE_GETCPU_VSYSCALL "__kernel_getcpu" - -#define HAVE_CLONE3_WRAPPER 1 -#endif +# define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres" +# define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime" +# define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom" +# define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday" +# define HAVE_GETCPU_VSYSCALL "__kernel_getcpu" + +# define HAVE_CLONE3_WRAPPER 1 + +# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL +# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 + +#endif /* __ASSEMBLER__ */ + +#endif /* _LINUX_S390_SYSDEP_H */ diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h index 9923199e407ccd8c3c341695841bcc07802c0189..f24ab4a9ee158d7f0890cd228b20bf1e278d332b 100644 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h +++ b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h @@ -1,19 +1,10 @@ /* Versions of the 'struct stat' data structure used in compatibility xstat functions. */ - -#include - -#if __WORDSIZE == 64 -# define _STAT_VER_KERNEL 0 -# define _STAT_VER_LINUX 1 -# define _MKNOD_VER_LINUX 0 -#else -# define _STAT_VER_LINUX_OLD 1 -# define _STAT_VER_KERNEL 1 -# define _STAT_VER_SVR4 2 -# define _STAT_VER_LINUX 3 -# define _MKNOD_VER_LINUX 1 -# define _MKNOD_VER_SVR4 2 -#endif +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 1 #define _STAT_VER _STAT_VER_LINUX + +/* Versions of the 'xmknod' interface used in compatibility xmknod + functions. */ +#define _MKNOD_VER_LINUX 0 #define _MKNOD_VER _MKNOD_VER_LINUX diff --git a/src/libs/glibc.zig b/src/libs/glibc.zig index 59abb61f333a8baf6ce54a485ff3dcdbdefd2afc..fce076dba86d74c52756d72419ed8859633992b5 100644 --- a/src/libs/glibc.zig +++ b/src/libs/glibc.zig @@ -398,7 +398,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![ try result.appendSlice("powerpc" ++ s ++ "powerpc32"); } } else if (arch == .s390x) { - try result.appendSlice("s390" ++ s ++ "s390-64"); + try result.appendSlice("s390"); } else if (arch.isLoongArch()) { try result.appendSlice("loongarch"); } else if (arch == .m68k) { @@ -607,8 +607,6 @@ fn add_include_dirs_arch( try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl })); } else { - try args.append("-I"); - try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" ++ s ++ "s390-64" })); try args.append("-I"); try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" })); } -- 2.54.0 From 012016103d5fca2cb6961bf2b3919b09f63e592d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 29 Jul 2026 08:41:28 +0200 Subject: [PATCH 086/215] std.zig.target: add loongarch32-linux-gnu[sf] --- lib/std/zig/target.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index e30cae2a6728a7df71e9bef14f194f6264809604..6e7eb636d3bc30cd40e402d3490ef4a5f438e219 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -46,6 +46,8 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .csky, .os = .linux, .abi = .gnueabi, .os_ver = .{ .major = 4, .minor = 20, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 }, .glibc_triple = "csky-linux-gnuabiv2-soft" }, .{ .arch = .csky, .os = .linux, .abi = .gnueabihf, .os_ver = .{ .major = 4, .minor = 20, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 }, .glibc_triple = "csky-linux-gnuabiv2" }, .{ .arch = .hexagon, .os = .linux, .abi = .musl, .os_ver = .{ .major = 3, .minor = 2, .patch = 102 } }, + .{ .arch = .loongarch32, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 6, .minor = 19, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 44, .patch = 0 }, .glibc_triple = "loongarch32-linux-gnuf64" }, + .{ .arch = .loongarch32, .os = .linux, .abi = .gnusf, .os_ver = .{ .major = 6, .minor = 19, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 44, .patch = 0 }, .glibc_triple = "loongarch32-linux-gnusf" }, .{ .arch = .loongarch64, .os = .linux, .abi = .gnu, .os_ver = .{ .major = 5, .minor = 19, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 }, .glibc_triple = "loongarch64-linux-gnuf64" }, .{ .arch = .loongarch64, .os = .linux, .abi = .gnusf, .os_ver = .{ .major = 5, .minor = 19, .patch = 0 }, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 }, .glibc_triple = "loongarch64-linux-gnusf" }, .{ .arch = .loongarch64, .os = .linux, .abi = .musl, .os_ver = .{ .major = 5, .minor = 19, .patch = 0 } }, -- 2.54.0 From 31e3a75b2f62b8d59365e09fa4436a4143a1327a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 29 Jul 2026 09:40:07 +0200 Subject: [PATCH 087/215] std.Target.DynamicLinker: define path for loongarch32-linux-gnu[f32,sf] --- lib/std/Target.zig | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 8ad977e5a528583032f075fb84b5c72fcc504d54..29440d64af025266aa10b860ffaeb69e9917c591 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -2660,12 +2660,26 @@ pub const DynamicLinker = struct { else => return none, }}), - .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) { - .gnu => "lp64d", - .gnuf32 => "lp64f", - .gnusf => "lp64s", - else => return none, - }}), + .loongarch32, + .loongarch64, + => |arch| initFmt("/lib{s}/ld-linux-{s}{s}.so.1", .{ + switch (arch) { + .loongarch32 => "32", + .loongarch64 => "64", + else => unreachable, + }, + switch (arch) { + .loongarch32 => "loongarch-ilp32", + .loongarch64 => "loongarch-lp64", + else => unreachable, + }, + switch (abi) { + .gnu => "d", + .gnuf32 => "f", + .gnusf => "s", + else => return none, + }, + }), .hppa, .m68k, -- 2.54.0 From b20d6761ca5117e42507b759811f4d4fab604c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 29 Jul 2026 09:40:39 +0200 Subject: [PATCH 088/215] test: add loongarch32-linux-gnu[sf] to llvm_targets --- test/llvm_targets.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig index 480adbcdafe6031de71b9ee42b8d9899c1faf72d..101c56df41624bd92404ddcb47c390eceeacc8e0 100644 --- a/test/llvm_targets.zig +++ b/test/llvm_targets.zig @@ -106,9 +106,9 @@ const targets = [_]std.Target.Query{ .{ .cpu_arch = .lanai, .os_tag = .freestanding, .abi = .none }, .{ .cpu_arch = .loongarch32, .os_tag = .freestanding, .abi = .none }, - // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnu }, + .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnu }, // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnuf32 }, - // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnusf }, + .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .gnusf }, // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .musl }, // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslf32 }, // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslsf }, -- 2.54.0 From b665f716f3d35b4ae1505fa4b95bea42da031785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 31 Jul 2026 23:06:09 +0200 Subject: [PATCH 089/215] test: partially disable glibc_compat on loongarch https://github.com/Vexu/arocc/issues/1096 --- test/standalone/glibc_compat/build.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/standalone/glibc_compat/build.zig b/test/standalone/glibc_compat/build.zig index 2a171c2dddab4c36fbee25c08eb5465e1b218cab..69568d72d9c1fd1b190aa482a0e1749feb7fa886 100644 --- a/test/standalone/glibc_compat/build.zig +++ b/test/standalone/glibc_compat/build.zig @@ -103,6 +103,8 @@ pub fn build(b: *std.Build) void { .{ .arch_os_abi = t }, ) catch unreachable); + if (target.result.cpu.arch.isLoongArch()) continue; // https://github.com/Vexu/arocc/issues/1096 + const glibc_ver = target.result.os.version_range.linux.glibc; // only build test if glibc version supports the architecture -- 2.54.0 From 91c6d8a092498b5d168cc8aaffdf72e0b825e340 Mon Sep 17 00:00:00 2001 From: Mason Remaley Date: Wed, 29 Jul 2026 02:28:19 -0700 Subject: [PATCH 090/215] Fix mistake in @Union langref --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 9a19c4d95d7fed570085253b090d20ee43d1edf4..1a0d531b591faabdac3d75367ababda8eafcfa6d 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5848,7 +5848,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val {#header_open|@Union#}

{#syntax#}@Union(
     comptime layout: std.lang.Type.ContainerLayout,
-    /// Either the integer tag type, or the integer backing type, depending on `layout`.
+    /// Either the enum tag type, or the integer backing type, depending on `layout`.
     comptime ArgType: ?type,
     comptime field_names: []const []const u8,
     comptime field_types: *const [field_names.len]type,
-- 
2.54.0


From f212e3716b7f687d552fdad5f15cd1f736039910 Mon Sep 17 00:00:00 2001
From: Ryan Liptak 
Date: Thu, 30 Jul 2026 21:10:50 -0700
Subject: [PATCH 091/215] Writer.Allocating.drain: avoid overallocating in
 certain situations

In scenarios where splat=1, `drain` would ensure 2x more unused capacity than necessary for the "pattern" bytes since `bytes.len` and `splat_len` would both be counting the same bytes for the `data[data.len - 1]` element.

Now, instead of ensuring `bytes.len + splat_len + 1` unused capacity within the loop, the total amount is calculated upfront and that much unused capacity (+ 1, see 8f4229158be69685b49f4e1ac446cd3677a2e63f) is ensured all at once.
---
 lib/std/Io/Writer.zig | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig
index ebfe6cd502f399501eeafdbdf44205ca6636e8d2..7a6f4468964c4b5f8c8a1a6ff86fcd6d7a63a6b4 100644
--- a/lib/std/Io/Writer.zig
+++ b/lib/std/Io/Writer.zig
@@ -2742,29 +2742,26 @@ pub const Allocating = struct {
 
     fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
         const a: *Allocating = @fieldParentPtr("writer", w);
-        const pattern = data[data.len - 1];
-        const splat_len = pattern.len * splat;
-        const start_len = a.writer.end;
         assert(data.len != 0);
-        for (data) |bytes| {
-            a.ensureUnusedCapacity(bytes.len + splat_len + 1) catch return error.WriteFailed;
+        const count = countSplat(data, splat);
+        a.ensureUnusedCapacity(count + 1) catch return error.WriteFailed;
+        for (data[0 .. data.len - 1]) |bytes| {
             @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes);
             a.writer.end += bytes.len;
         }
-        if (splat == 0) {
-            a.writer.end -= pattern.len;
-        } else switch (pattern.len) {
+        const pattern = data[data.len - 1];
+        switch (pattern.len) {
             0 => {},
             1 => {
-                @memset(a.writer.buffer[a.writer.end..][0 .. splat - 1], pattern[0]);
-                a.writer.end += splat - 1;
+                @memset(a.writer.buffer[a.writer.end..][0..splat], pattern[0]);
+                a.writer.end += splat;
             },
-            else => for (0..splat - 1) |_| {
+            else => for (0..splat) |_| {
                 @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern);
                 a.writer.end += pattern.len;
             },
         }
-        return a.writer.end - start_len;
+        return count;
     }
 
     fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
-- 
2.54.0


From f134f4345cf8484b82c46278074eb45af0efaf2e Mon Sep 17 00:00:00 2001
From: Matthew Lugg 
Date: Fri, 31 Jul 2026 13:39:16 +0100
Subject: [PATCH 092/215] compiler: improve tracking of transitive analysis
 errors

This is an internal refactor to mark transitive semantic analysis errors
as soon as they occur rather than relying on the root "update" function
to do so. This is simpler to understand and slightly more efficient. The
error surfaced in this case is renamed from `error.AnalysisFail` to
`error.AlreadyReported` for consistency with the rest of the compiler.
`error.AnalysisFail` is returned from the "ensure up to date" functions
in `Zcu.PerThread` to indicate that the unit which was requested has
failed analysis---using a different error name here is useful because it
prevents `Sema` from accidentally introducing a bug by `try`ing.

Alongside the above, I have also begun to store some useful debugging
information (the reason for the transitive analysis error) with
transitive analysis errors in compilers built with debug extensions.
This information is surfaced by the incremental debug server, and was
invaluable in tracking down an incremental compilation bug---details of
that in the next commit.
---
 src/Compilation.zig            |   9 +-
 src/IncrementalDebugServer.zig |  27 +++--
 src/Sema.zig                   | 185 ++++++++++++++++++++++++---------
 src/Sema/LowerZon.zig          |   4 +-
 src/Sema/type_resolution.zig   |  28 +++--
 src/Zcu.zig                    |  21 +++-
 src/Zcu/PerThread.zig          | 163 +++++++++++++----------------
 7 files changed, 275 insertions(+), 162 deletions(-)

diff --git a/src/Compilation.zig b/src/Compilation.zig
index 6561f88312664801ea4dc1d217ecf85ae413c1af..0952e9f7dc05456c4a8d4e6cbc35fa17d14ef484 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -4076,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
                     ref = refs.get(r.referencer).?;
                 }
             }
-            @panic("referenced transitive analysis errors, but none actually emitted");
+            if (comp.debugIncremental()) {
+                std.debug.print("skipping compiler panic to allow incremental debug server usage", .{});
+                try bundle.addRootErrorMessage(.{
+                    .msg = try bundle.addString("compiler bug: referenced transitive analysis errors, but none actually emitted"),
+                });
+            } else {
+                @panic("referenced transitive analysis errors, but none actually emitted");
+            }
         }
     };
 
diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig
index 4d34812ae507191ea3799f12209d482008e14b93..20c1af1969ad117ee63acd6428f1ee0c8490f6e6 100644
--- a/src/IncrementalDebugServer.zig
+++ b/src/IncrementalDebugServer.zig
@@ -286,21 +286,34 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
             const referencer = (ref orelse break :ref "").referencer;
             break :ref printAnalUnit(referencer, &ref_str_buf);
         };
-        const has_err: []const u8 = err: {
-            if (zcu.failed_analysis.contains(unit)) break :err "true";
-            if (zcu.transitive_failed_analysis.contains(unit)) break :err "true (transitive)";
-            break :err "false";
-        };
         try w.print(
             \\last update generation: {d}
             \\current referencer: {s}
-            \\has error: {s}
             \\
         , .{
             unit_info.last_update_gen,
             ref_str,
-            has_err,
         });
+        if (zcu.failed_analysis.get(unit)) |err_msg| {
+            try w.print("analysis result: failure ({q})\n", .{err_msg.msg});
+        } else if (zcu.transitive_failed_analysis.get(unit)) |reason| {
+            switch (reason) {
+                .astgen_error => try w.writeAll("analysis result: transitive failure (astgen error)\n"),
+                .dependency_loop => try w.writeAll("analysis result: transitive failure (dependency loop)\n"),
+                .lost_tracking => try w.writeAll("analysis result: transitive failure (lost tracking for zir inst)\n"),
+                .failed_unit => |other_unit| {
+                    var buf: [32]u8 = undefined;
+                    try w.print("analysis result: transitive failure (failed unit: {s})\n", .{printAnalUnit(other_unit, &buf)});
+                },
+                .func_nav_val_changed => |func_index| try w.print("analysis result: transitive failure (owner nav of func '{d}' changed value)\n", .{@backingInt(func_index)}),
+            }
+        } else {
+            try w.writeAll("analysis result: success\n");
+        }
+        if (unit.unwrap() == .func) {
+            const nav_id = zcu.intern_pool.indexToKey(unit.unwrap().func).func.owner_nav;
+            try w.print("owner nav: {d}\n", .{@backingInt(nav_id)});
+        }
     } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {
         const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");
         const unit_info = zcu.incremental_debug_state.units.get(unit) orelse return w.writeAll("unknown anal unit");
diff --git a/src/Sema.zig b/src/Sema.zig
index 2181fa563b9e9dec42b1123cc3b738874df64ca7..09268824c6dd2063f6a94d836416a36375c11e42 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(
                         i += 1;
                         continue;
                     },
-                    .astgen_error => return error.AnalysisFail,
+                    .astgen_error => return sema.failTransitive(.astgen_error),
                     .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),
                 };
             },
@@ -2697,13 +2697,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
     });
 }
 
-pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {
+pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) SemaError {
     @branchHint(.cold);
     const zcu = sema.pt.zcu;
     const comp = zcu.comp;
     const gpa = comp.gpa;
     const io = comp.io;
 
+    assert(sema.err == null);
+
     if (build_options.enable_debug_extensions and comp.debug_compile_errors) {
         var wip_errors: std.zig.ErrorBundle.Wip = undefined;
         wip_errors.init(gpa) catch @panic("out of memory");
@@ -2729,17 +2731,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
 
     err_msg.reference_trace_root = sema.owner.toOptional();
 
-    const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);
-    if (gop.found_existing) {
-        // If there are multiple errors for the same Decl, prefer the first one added.
-        sema.err = null;
-        err_msg.destroy(gpa);
-    } else {
-        sema.err = err_msg;
-        gop.value_ptr.* = err_msg;
-    }
+    try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg);
+    assert(!zcu.transitive_failed_analysis.contains(sema.owner));
 
-    return error.AnalysisFail;
+    sema.err = err_msg;
+    return error.AlreadyReported;
 }
 
 /// Given an ErrorMsg, modify its message and source location to the given values, turning the
@@ -4745,11 +4741,14 @@ fn failWithBadMemberAccess(
         .@"enum" => "enum",
         else => unreachable,
     };
-    if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {
-        return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
-            agg_ty.fmt(pt), field_name.fmt(ip),
-        });
-    };
+    if (agg_ty.typeDeclInst(zcu)) |inst| {
+        const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst });
+        if (inst_index == .main_struct_inst) {
+            return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
+                agg_ty.fmt(pt), field_name.fmt(ip),
+            });
+        }
+    }
 
     return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
         kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
@@ -5997,7 +5996,14 @@ fn lookupInNamespace(
     const pt = sema.pt;
     const zcu = pt.zcu;
 
-    try pt.ensureNamespaceUpToDate(namespace_index);
+    pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
+        error.LostZirContainerDecl => {
+            const namespace = zcu.namespacePtr(namespace_index);
+            const ns_ty: Type = .fromInterned(namespace.owner_type);
+            return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
+        },
+        else => |e| return e,
+    };
 
     const namespace = zcu.namespacePtr(namespace_index);
 
@@ -6062,7 +6068,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
     const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);
     const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
     const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
-        error.AnalysisFail => @panic("std.lang.StackTrace is corrupt"),
+        error.AlreadyReported => @panic("std.lang.StackTrace is corrupt"),
         error.ComptimeReturn, error.ComptimeBreak => unreachable,
         error.OutOfMemory, error.Canceled => |e| return e,
     };
@@ -6724,7 +6730,9 @@ fn analyzeCall(
     const fn_nav: InternPool.Nav, const fn_zir: Zir, const fn_tracked_inst: InternPool.TrackedInst.Index, const fn_zir_inst: Zir.Inst.Index, const fn_zir_info: Zir.FnInfo = if (func_val) |f| b: {
         const info = ip.indexToKey(f.toIntern()).func;
         const nav = ip.getNav(info.owner_nav);
-        const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail;
+        const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse {
+            return sema.failTransitive(.{ .lost_tracking = info.zir_body_inst });
+        };
         const file = zcu.fileByIndex(resolved_func_inst.file);
         const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);
         break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };
@@ -8355,7 +8363,10 @@ fn zirFunc(
     const cc: std.lang.CallingConvention = if (has_body) cc: {
         const func_decl_nav = sema.owner.unwrap().nav_val;
         const fn_is_exported = exported: {
-            const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;
+            const decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
+            const decl_inst = decl_ti.resolve(ip) orelse {
+                return sema.failTransitive(.{ .lost_tracking = decl_ti });
+            };
             const zir_decl = sema.code.getDeclaration(decl_inst);
             break :exported zir_decl.linkage == .@"export";
         };
@@ -12289,10 +12300,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
             dummy_captures,
             .{ .override = item_srcs },
         ) catch |err| switch (err) {
-            error.AnalysisFail => {
-                const msg = sema.err orelse return error.AnalysisFail;
-                try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
-                return error.AnalysisFail;
+            error.AlreadyReported => |e| {
+                if (sema.err) |msg| {
+                    try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
+                }
+                return e;
             },
             else => |e| return e,
         };
@@ -12328,11 +12340,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
                 dummy_captures,
                 .{ .override = item_srcs },
             ) catch |err| switch (err) {
-                error.AnalysisFail => {
-                    const msg = sema.err orelse return error.AnalysisFail;
-                    try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});
-                    try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
-                    return error.AnalysisFail;
+                error.AlreadyReported => |e| {
+                    if (sema.err) |msg| {
+                        try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});
+                        try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
+                    }
+                    return e;
                 },
                 else => |e| return e,
             };
@@ -17207,7 +17220,14 @@ fn typeInfoNamespaceDecls(
     const ip = &zcu.intern_pool;
 
     const namespace_index = opt_namespace_index.unwrap() orelse return;
-    try pt.ensureNamespaceUpToDate(namespace_index);
+    pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
+        error.LostZirContainerDecl => {
+            const namespace = zcu.namespacePtr(namespace_index);
+            const ns_ty: Type = .fromInterned(namespace.owner_type);
+            return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
+        },
+        else => |e| return e,
+    };
     const namespace = zcu.namespacePtr(namespace_index);
 
     const gop = try seen_namespaces.getOrPut(namespace);
@@ -17933,11 +17953,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
     }
     // TODO Add compile error for @optimizeFor occurring too late in a scope.
     sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {
-        error.AnalysisFail => {
-            const msg = sema.err orelse return err;
-            if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;
-            try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
-            return err;
+        error.AlreadyReported => |e| {
+            if (sema.err) |msg| {
+                if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;
+                try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
+            }
+            return e;
         },
         else => |e| return e,
     };
@@ -18353,11 +18374,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
 
     const elem_ty = blk: {
         const air_inst = sema.resolveInst(extra.data.elem_type);
-        const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| {
-            if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) {
-                try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
-            }
-            return err;
+        const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| switch (err) {
+            error.AlreadyReported => |e| {
+                if (sema.err) |msg| {
+                    if (sema.typeOf(air_inst).isSinglePointer(zcu)) {
+                        try sema.errNote(elem_ty_src, msg, "use '.*' to dereference pointer", .{});
+                    }
+                }
+                return e;
+            },
+            else => |e| return e,
         };
         assert(!ty.isGenericPoison());
         break :blk ty;
@@ -24909,7 +24935,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
     } else cc: {
         if (has_body) {
             const func_decl_nav = sema.owner.unwrap().nav_val;
-            const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;
+            const func_decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
+            const func_decl_inst = func_decl_ti.resolve(&zcu.intern_pool) orelse {
+                return sema.failTransitive(.{ .lost_tracking = func_decl_ti });
+            };
             const zir_decl = sema.code.getDeclaration(func_decl_inst);
             if (zir_decl.linkage == .@"export") {
                 break :cc target.cCallingConvention() orelse {
@@ -30642,7 +30671,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
     if (pt.zcu.analysis_in_progress.contains(unit)) {
         return sema.failWithDependencyLoop(unit, &reason);
     }
-    try pt.ensureMemoizedStateUpToDate(stage, &reason);
+    pt.ensureMemoizedStateUpToDate(stage, &reason) catch |err| switch (err) {
+        error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = unit }),
+        else => |e| return e,
+    };
 }
 
 pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
@@ -30678,9 +30710,15 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
     switch (kind) {
         .type => {
             try zcu.ensureNavValAnalysisQueued(nav_index);
-            return pt.ensureNavTypeUpToDate(nav_index, &reason);
+            return pt.ensureNavTypeUpToDate(nav_index, &reason) catch |err| switch (err) {
+                error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
+                else => |e| return e,
+            };
+        },
+        .fully => return pt.ensureNavValUpToDate(nav_index, &reason) catch |err| switch (err) {
+            error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
+            else => |e| return e,
         },
-        .fully => return pt.ensureNavValUpToDate(nav_index, &reason),
     }
 }
 
@@ -33743,7 +33781,10 @@ fn ensureFuncIesResolved(
         return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);
     }
 
-    try pt.ensureFuncBodyUpToDate(func_index, &reason);
+    pt.ensureFuncBodyUpToDate(func_index, &reason) catch |err| switch (err) {
+        error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .func = func_index }) }),
+        else => |e| return e,
+    };
 }
 
 pub fn resolveInferredErrorSetPtr(
@@ -34962,7 +35003,9 @@ pub fn setTypeName(
         },
         .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),
         .func => {
-            const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
+            const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse {
+                return sema.failTransitive(.{ .lost_tracking = ip.funcZirBodyInst(sema.func_index) });
+            });
             const zir_tags = sema.code.instructions.items(.tag);
 
             var aw: std.Io.Writer.Allocating = .init(gpa);
@@ -35078,7 +35121,10 @@ fn zirStructDecl(
     };
 
     try sema.addTypeReferenceEntry(src, ty);
-    try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
+    pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
+        error.LostZirContainerDecl => unreachable, // we literally just tracked it
+        else => |e| return e,
+    };
 
     return .fromType(ty);
 }
@@ -35151,7 +35197,10 @@ fn zirUnionDecl(
     };
 
     try sema.addTypeReferenceEntry(src, ty);
-    try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
+    pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
+        error.LostZirContainerDecl => unreachable, // we literally just tracked it
+        else => |e| return e,
+    };
 
     return .fromType(ty);
 }
@@ -35203,7 +35252,10 @@ fn zirEnumDecl(
     };
 
     try sema.addTypeReferenceEntry(src, ty);
-    try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
+    pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
+        error.LostZirContainerDecl => unreachable, // we literally just tracked it
+        else => |e| return e,
+    };
 
     return .fromType(ty);
 }
@@ -35252,7 +35304,10 @@ fn zirOpaqueDecl(
     };
 
     try sema.addTypeReferenceEntry(src, ty);
-    try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
+    pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
+        error.LostZirContainerDecl => unreachable, // we literally just tracked it
+        else => |e| return e,
+    };
 
     return .fromType(ty);
 }
@@ -35293,5 +35348,31 @@ pub fn failWithDependencyLoop(
     }
 
     // A dependency loop error will be reported. Mark us all as transitive failures.
-    return error.AnalysisFail;
+    return sema.failTransitive(.dependency_loop);
+}
+
+/// Marks the owner of `sema` as having failed semantic failed *without* an error message, and
+/// returns failure. This function is suitable to call when any one of the following is true:
+///
+/// * `sema.owner` is guaranteed to be unreferenced on this update, for instance because it uses a
+///   dead `InternPool.TrackedInst`.
+///
+/// * There is guaranteed to be a compile error if this unit is referenced. In practice, this means
+///   that either there is an error elsewhere in the pipeline (e.g. AstGen), or we depend on another
+///   `AnalUnit` which has itself failed.
+pub fn failTransitive(sema: *Sema, reason: Zcu.TransitiveFailureReason) SemaError {
+    assert(sema.err == null);
+    const zcu = sema.pt.zcu;
+    const unit = sema.owner;
+
+    log.debug("transitive failure analyzing '{f}' ({t})", .{ zcu.fmtAnalUnit(unit), reason });
+
+    assert(!zcu.failed_analysis.contains(unit));
+    try zcu.transitive_failed_analysis.putNoClobber(
+        zcu.comp.gpa,
+        unit,
+        if (build_options.enable_debug_extensions) reason,
+    );
+
+    return error.AlreadyReported;
 }
diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig
index f807043d8ecd7bbf6c628feb877d25c92212d08c..dd8c91c244518ac23d1d5d0be6caa30861f2c4c7 100644
--- a/src/Sema/LowerZon.zig
+++ b/src/Sema/LowerZon.zig
@@ -320,7 +320,7 @@ fn failUnsupportedResultType(
     self: *LowerZon,
     ty: Type,
     opt_note: ?[]const u8,
-) error{ AnalysisFail, OutOfMemory } {
+) Zcu.SemaError {
     @branchHint(.cold);
     const sema = self.sema;
     const gpa = sema.gpa;
@@ -338,7 +338,7 @@ fn fail(
     node: Zoir.Node.Index,
     comptime format: []const u8,
     args: anytype,
-) error{ AnalysisFail, OutOfMemory } {
+) Zcu.SemaError {
     @branchHint(.cold);
     const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);
     try self.sema.pt.zcu.errNote(self.import_loc, err_msg, "imported here", .{});
diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig
index b3de4f8433a768a6a5c4c174fb300f1a899edf64..1e089955e59e2efcbd3b40185cab8289460c956f 100644
--- a/src/Sema/type_resolution.zig
+++ b/src/Sema/type_resolution.zig
@@ -116,7 +116,10 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
             if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {
                 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);
             }
-            try pt.ensureTypeLayoutUpToDate(ty, reason);
+            pt.ensureTypeLayoutUpToDate(ty, reason) catch |err| switch (err) {
+                error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .type_layout = ty.toIntern() }) }),
+                else => |e| return e,
+            };
         },
 
         // values, not types
@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema
         return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);
     }
 
-    try pt.ensureStructDefaultsUpToDate(ty, &reason);
+    pt.ensureStructDefaultsUpToDate(ty, &reason) catch |err| switch (err) {
+        error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .struct_defaults = ty.toIntern() }) }),
+        else => |e| return e,
+    };
 }
 
 /// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.
@@ -188,7 +194,9 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
 
     const struct_obj = ip.loadStructType(struct_ty.toIntern());
     assert(struct_obj.want_layout);
-    const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
+    const zir_index = struct_obj.zir_index.resolve(ip) orelse {
+        return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
+    };
 
     var block: Block = .{
         .parent = null,
@@ -606,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
     struct_ty.assertHasLayout(zcu);
     const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });
     if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) {
-        return error.AnalysisFail;
+        return sema.failTransitive(.{ .failed_unit = layout_unit });
     }
 
     const struct_obj = ip.loadStructType(struct_ty.toIntern());
@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(
     assert(struct_obj.field_defaults.len > 0);
 
     // We'll need to map the struct decl instruction to provide result types
-    const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
+    const zir_index = struct_obj.zir_index.resolve(ip) orelse {
+        return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
+    };
     try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
 
     const field_types = struct_obj.field_types.get(ip);
@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
 
     const union_obj = ip.loadUnionType(union_ty.toIntern());
     assert(union_obj.want_layout);
-    const zir_index = union_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
+    const zir_index = union_obj.zir_index.resolve(ip) orelse {
+        return sema.failTransitive(.{ .lost_tracking = union_obj.zir_index });
+    };
 
     var block: Block = .{
         .parent = null,
@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
     };
 
     const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;
-    const zir_index = tracked_inst.resolve(ip) orelse return error.AnalysisFail;
+    const zir_index = tracked_inst.resolve(ip) orelse {
+        return sema.failTransitive(.{ .lost_tracking = tracked_inst });
+    };
 
     var block: Block = .{
         .parent = null,
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 9ed2ed7dc708d3939a1baf479fdd11798415e6fb..465506eb7b41dcbcb16620c7ef84dc8b5f406ea4 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason
 /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
 failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,
 /// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.
-transitive_failed_analysis: std.array_hash_map.Auto(AnalUnit, void) = .empty,
+transitive_failed_analysis: std.array_hash_map.Auto(
+    AnalUnit,
+    if (build_options.enable_debug_extensions) TransitiveFailureReason else void,
+) = .empty,
 /// 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.
@@ -351,6 +354,18 @@ pub const DependencyReason = struct {
     type_layout_reason: Sema.type_resolution.LayoutResolveReason,
 };
 
+/// These are not required for anything, but when the compiler is built with debug extensions, we
+/// store these in `Zcu.transitive_failed_analysis` and surface them in the incremental debug server
+/// (see `src/IncrementalDebugServer.zig`) because they are a useful debugging aid for bugs in
+/// incremental compilation.
+pub const TransitiveFailureReason = union(enum) {
+    astgen_error,
+    dependency_loop,
+    lost_tracking: InternPool.TrackedInst.Index,
+    failed_unit: AnalUnit,
+    func_nav_val_changed: InternPool.Index,
+};
+
 pub const IncrementalDebugState = struct {
     /// All container types in the ZCU, even dead ones.
     /// Value is the generation the type was created on.
@@ -2808,13 +2823,13 @@ pub const LazySrcLoc = struct {
     }
 };
 
-pub const SemaError = error{ OutOfMemory, Canceled, AnalysisFail };
+pub const SemaError = error{ OutOfMemory, Canceled, AlreadyReported };
 pub const CompileError = error{
     OutOfMemory,
     /// The compilation update is no longer desired.
     Canceled,
     /// When this is returned, the compile error for the failure has already been recorded.
-    AnalysisFail,
+    AlreadyReported,
     /// In a comptime scope, a return instruction was encountered. This error is only seen when
     /// doing a comptime function call.
     ComptimeReturn,
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index b1292e6dedb38753832091e60c5535343dfef0c2..d062f68ec946d85481b9a29c5c2eb5de5cf6e5ca 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -320,7 +320,7 @@ pub fn update(
     // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,
     // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.
     while (try zcu.findOutdatedToAnalyze()) |unit| {
-        const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {
+        const maybe_err: UpdateUnitError!void = switch (unit.unwrap()) {
             .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
             .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),
             .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),
@@ -332,7 +332,7 @@ pub fn update(
                     error.Canceled,
                     => |e| return e,
 
-                    error.AnalysisFail => {}, // already reported
+                    error.AnalysisFail => {},
                 };
                 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);
             },
@@ -344,7 +344,7 @@ pub fn update(
             error.Canceled,
             => |e| return e,
 
-            error.AnalysisFail => {}, // already reported
+            error.AnalysisFail => {},
         };
     }
 }
@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
 
 /// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
 /// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`
-/// is populated. Does not return `error.AnalysisFail` on AstGen failures.
+/// is populated. Returns success even if the file has AstGen errors.
 pub fn updateFile(
     pt: Zcu.PerThread,
     file_index: Zcu.File.Index,
@@ -1036,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc
     zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));
 }
 
+const UpdateUnitError = Allocator.Error || Io.Cancelable || error{
+    /// Semantic analysis of this `AnalUnit` failed.
+    AnalysisFail,
+};
+
 /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
 /// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore
 /// this, since the error is already registered, but it must not use the value of memoized fields.
@@ -1044,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(
     stage: InternPool.MemoizedStateStage,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     const zcu = pt.zcu;
     const gpa = zcu.gpa;
 
@@ -1078,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(
     const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|
         .{ any_changed or prev_failed, false }
     else |err| switch (err) {
-        error.AnalysisFail => res: {
-            if (!zcu.failed_analysis.contains(unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)});
-            }
-            break :res .{ !prev_failed, true };
-        },
+        error.AlreadyReported => .{ !prev_failed, true },
         error.OutOfMemory => {
             // TODO: same as for `ensureComptimeUnitUpToDate` etc
             return error.OutOfMemory;
@@ -1154,7 +1151,7 @@ fn analyzeMemoizedState(
 /// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
 /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
 /// free to ignore this, since the error is already registered.
-pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void {
+pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) UpdateUnitError!void {
     const zcu = pt.zcu;
     const gpa = zcu.gpa;
 
@@ -1195,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
     defer unit_tracking.end(zcu);
 
     return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
-        error.AnalysisFail => {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            return error.AnalysisFail;
-        },
+        error.AlreadyReported => return error.AnalysisFail,
         error.OutOfMemory => {
             // TODO: it's unclear how to gracefully handle this.
             // To report the error cleanly, we need to add a message to `failed_analysis` and a
@@ -1221,8 +1210,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
 
 /// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
 /// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this
-/// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry
-/// to `transitive_failed_analysis` if necessary.
+/// function will return `error.AlreadyReported`.
 fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
@@ -1239,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
     defer tracy_trace.end();
     tracy_trace.addTextFmt("cu_id={d}", .{cu_id});
 
-    const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
+    const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse {
+        try zcu.transitive_failed_analysis.putNoClobber(
+            gpa,
+            anal_unit,
+            if (build_options.enable_debug_extensions) .{ .lost_tracking = comptime_unit.zir_index },
+        );
+        return error.AlreadyReported;
+    };
     const file = zcu.fileByIndex(inst_resolved.file);
     const zir = file.zir.?;
 
@@ -1314,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(
     ty: Type,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
     const comp = zcu.comp;
@@ -1399,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(
     const new_failed: bool = if (result) failed: {
         break :failed false;
     } else |err| switch (err) {
-        error.AnalysisFail => failed: {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            break :failed true;
-        },
+        error.AlreadyReported => true,
         error.OutOfMemory,
         error.Canceled,
         => |e| return e,
@@ -1442,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(
     ty: Type,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
     const comp = zcu.comp;
@@ -1513,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(
     const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {
         break :failed false;
     } else |err| switch (err) {
-        error.AnalysisFail => failed: {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            break :failed true;
-        },
+        error.AlreadyReported => true,
         error.OutOfMemory,
         error.Canceled,
         => |e| return e,
@@ -1547,7 +1526,7 @@ pub fn ensureNavValUpToDate(
     nav_id: InternPool.Nav.Index,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     const zcu = pt.zcu;
     const gpa = zcu.gpa;
     const ip = &zcu.intern_pool;
@@ -1594,15 +1573,7 @@ pub fn ensureNavValUpToDate(
             false,
         };
     } else |err| switch (err) {
-        error.AnalysisFail => res: {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            break :res .{ !prev_failed, true };
-        },
+        error.AlreadyReported => .{ !prev_failed, true },
         error.OutOfMemory => {
             // TODO: it's unclear how to gracefully handle this.
             // To report the error cleanly, we need to add a message to `failed_analysis` and a
@@ -1655,7 +1626,14 @@ fn analyzeNavVal(
     tracy_trace.addText(old_nav.fqn.toSlice(ip));
     tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
 
-    const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
+    const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
+        try zcu.transitive_failed_analysis.putNoClobber(
+            gpa,
+            anal_unit,
+            if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
+        );
+        return error.AlreadyReported;
+    };
     const file = zcu.fileByIndex(inst_resolved.file);
     const zir = file.zir.?;
     const zir_decl = zir.getDeclaration(inst_resolved.inst);
@@ -1916,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(
     nav_id: InternPool.Nav.Index,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     const zcu = pt.zcu;
     const gpa = zcu.gpa;
     const ip = &zcu.intern_pool;
@@ -1963,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(
             false,
         };
     } else |err| switch (err) {
-        error.AnalysisFail => res: {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this unit caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            break :res .{ !prev_failed, true };
-        },
+        error.AlreadyReported => .{ !prev_failed, true },
         error.OutOfMemory => {
             // TODO: it's unclear how to gracefully handle this.
             // To report the error cleanly, we need to add a message to `failed_analysis` and a
@@ -2024,7 +1994,14 @@ fn analyzeNavType(
     tracy_trace.addText(old_nav.fqn.toSlice(ip));
     tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
 
-    const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
+    const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
+        try zcu.transitive_failed_analysis.putNoClobber(
+            gpa,
+            anal_unit,
+            if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
+        );
+        return error.AlreadyReported;
+    };
     const file = zcu.fileByIndex(inst_resolved.file);
     const zir = file.zir.?;
 
@@ -2160,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(
     func_index: InternPool.Index,
     /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
     reason: ?*const Zcu.DependencyReason,
-) Zcu.SemaError!void {
+) UpdateUnitError!void {
     dev.check(.sema);
 
     const zcu = pt.zcu;
@@ -2204,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(
     const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|
         .{ prev_failed or result.ies_outdated, false }
     else |err| switch (err) {
-        error.AnalysisFail => res: {
-            if (!zcu.failed_analysis.contains(anal_unit)) {
-                // If this function caused the error, it would have an entry in `failed_analysis`.
-                // Since it does not, this must be a transitive failure.
-                try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
-                log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
-            }
-            // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
-            // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
-            // a different error later (which may now be invalid).
-            break :res .{ !prev_failed, true };
-        },
+        // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
+        // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
+        // a different error later (which may now be invalid).
+        error.AlreadyReported => .{ !prev_failed, true },
         error.OutOfMemory => {
             // TODO: it's unclear how to gracefully handle this.
             // To report the error cleanly, we need to add a message to `failed_analysis` and a
@@ -3306,15 +3275,21 @@ fn analyzeFuncBodyInner(
     // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
 
     if (func.generic_owner == .none) {
-        try pt.ensureNavValUpToDate(func.owner_nav, reason);
+        pt.ensureNavValUpToDate(func.owner_nav, reason) catch |err| switch (err) {
+            error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = func.owner_nav }) }),
+            else => |e| return e,
+        };
         if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {
-            return error.AnalysisFail;
+            return sema.failTransitive(.{ .func_nav_val_changed = func_index });
         }
     } else {
         const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
-        try pt.ensureNavValUpToDate(go_nav, reason);
+        pt.ensureNavValUpToDate(go_nav, reason) catch |err| switch (err) {
+            error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = go_nav }) }),
+            else => |e| return e,
+        };
         if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) {
-            return error.AnalysisFail;
+            return sema.failTransitive(.{ .func_nav_val_changed = func.generic_owner });
         }
     }
 
@@ -3344,7 +3319,9 @@ fn analyzeFuncBodyInner(
     };
     defer inner_block.instructions.deinit(gpa);
 
-    const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse return error.AnalysisFail);
+    const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse {
+        return sema.failTransitive(.{ .lost_tracking = func.zirBodyInstUnordered(ip) });
+    });
 
     // Here we are performing "runtime semantic analysis" for a function body, which means
     // we must map the parameter ZIR instructions to `arg` AIR instructions.
@@ -4378,12 +4355,18 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable |
     return result.index;
 }
 
+const UpdateNamespaceError = Allocator.Error || Io.Cancelable || error{
+    /// This namespace refers to a ZIR container declaration which no longer exists, so any code
+    /// referencing it is guaranteed to be unreferenced on this update.
+    LostZirContainerDecl,
+};
+
 /// Given a namespace, re-scan its declarations from the type definition if they have not
 /// yet been re-scanned on this update.
-/// If the type declaration instruction has been lost, returns `error.AnalysisFail`.
+/// If the type declaration instruction has been lost, returns `error.LostZirContainerDecl`.
 /// This will effectively short-circuit the caller, which will be semantic analysis of a
 /// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error.
-pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) Zcu.SemaError!void {
+pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) UpdateNamespaceError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
     const namespace = zcu.namespacePtr(namespace_index);
@@ -4410,7 +4393,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
 
     // Namespace outdated -- re-scan the type if necessary.
 
-    const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
+    const inst_info = key.zir_index.resolveFull(ip) orelse return error.LostZirContainerDecl;
     const file = zcu.fileByIndex(inst_info.file);
     const zir = &file.zir.?;
 
-- 
2.54.0


From 804c284d2a4ece85aec64d25c241a48b4e8b11ad Mon Sep 17 00:00:00 2001
From: Matthew Lugg 
Date: Sat, 1 Aug 2026 09:32:18 +0100
Subject: [PATCH 093/215] incremental: fix incorrect dependency in generic
 instances

When analyzing the body of a generic function instance, we were making a
dependency on the owner NAV of the *instance*, rather than that of our
generic owner. Aside from being nonsensical (because the instance's
owner NAV does not undergo semantic analysis), this meant that if the
generic owner's owner NAV had a compile error (due to e.g. an error in
the function signature), then analysis of the generic instance's body
would fail, but it would not register a dependency on that NAV's value,
so would not be re-analyzed if the NAV suceeded in a future update.

Based on descriptions of when people had been hitting the dreaded
"referenced transitive analysis errors, but none actually emitted"
error, I *think* this was by far the most serious remaining incremental
compilation bug in the frontend---every description I've had of such a
crash occurring seems to more-or-less line up with this bug. So fingers
crossed this is another big jump in incremental compilation stability!
---
 src/Zcu/PerThread.zig                         |  4 +-
 ...porary_analysis_error_in_generic_signature | 46 +++++++++++++++++++
 2 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 test/incremental/temporary_analysis_error_in_generic_signature

diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index d062f68ec946d85481b9a29c5c2eb5de5cf6e5ca..4092f27b8b7ca16a56b412805779584b801561f9 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -3262,9 +3262,7 @@ fn analyzeFuncBodyInner(
     defer sema.deinit();
 
     // Every runtime function has a dependency on the source of the Decl it originates from.
-    // It also depends on the value of its owner Decl.
     try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });
-    try sema.declareDependency(.{ .nav_val = func.owner_nav });
 
     // Make sure that the declaration `Nav` still refers to this function (or its generic owner).
     // This will not be the case if the incremental update has changed a function type or turned a
@@ -3275,6 +3273,7 @@ fn analyzeFuncBodyInner(
     // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
 
     if (func.generic_owner == .none) {
+        try sema.declareDependency(.{ .nav_val = func.owner_nav });
         pt.ensureNavValUpToDate(func.owner_nav, reason) catch |err| switch (err) {
             error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = func.owner_nav }) }),
             else => |e| return e,
@@ -3284,6 +3283,7 @@ fn analyzeFuncBodyInner(
         }
     } else {
         const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
+        try sema.declareDependency(.{ .nav_val = go_nav });
         pt.ensureNavValUpToDate(go_nav, reason) catch |err| switch (err) {
             error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = go_nav }) }),
             else => |e| return e,
diff --git a/test/incremental/temporary_analysis_error_in_generic_signature b/test/incremental/temporary_analysis_error_in_generic_signature
new file mode 100644
index 0000000000000000000000000000000000000000..d8db72050b3af1164a312e1e7a1ed1f89bfc3dae
--- /dev/null
+++ b/test/incremental/temporary_analysis_error_in_generic_signature
@@ -0,0 +1,46 @@
+#update=initial version
+#file=main.zig
+//! The original repro here depends on re-analysis order, which depends on
+//! declaration order, so this exact declaration order must be used.
+const Foo = struct { x: u8 };
+pub fn main(init: std.process.Init) !void {
+    const c = bar('Z').x;
+    try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
+}
+fn bar(comptime x: u8) @This().Foo {
+    return .{ .x = x };
+}
+const std = @import("std");
+#expect_stdout="Z\n"
+
+#update=change generic signature to use non-existent member
+#file=main.zig
+//! The original repro here depends on re-analysis order, which depends on
+//! declaration order, so this exact declaration order must be used.
+const Foo = struct { x: u8 };
+pub fn main(init: std.process.Init) !void {
+    const c = bar('Z').x;
+    try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
+}
+fn bar(comptime x: u8) @This().FooAlias {
+    return .{ .x = x };
+}
+const std = @import("std");
+#expect_error=main.zig:8:31: error: root source file struct 'main' has no member named 'FooAlias'
+#expect_error=main.zig:1:1: note: struct declared here
+
+#update=add that member, fixing the error
+#file=main.zig
+//! The original repro here depends on re-analysis order, which depends on
+//! declaration order, so this exact declaration order must be used.
+const Foo = struct { x: u8 };
+const FooAlias = Foo;
+pub fn main(init: std.process.Init) !void {
+    const c = bar('Z').x;
+    try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
+}
+fn bar(comptime x: u8) @This().FooAlias {
+    return .{ .x = x };
+}
+const std = @import("std");
+#expect_stdout="Z\n"
-- 
2.54.0


From 5245c13a8a46520127600845f1c9ab5bca42ded5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 11:32:32 +0200
Subject: [PATCH 094/215] std.heap.PageAllocator: disable hinting on
 sparc[64]-linux

https://bugzilla.kernel.org/show_bug.cgi?id=221820
---
 lib/std/heap/PageAllocator.zig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/std/heap/PageAllocator.zig b/lib/std/heap/PageAllocator.zig
index db736036b3f416d34a934b7185ac4a953affa303..1adac776bb9ac7a1d145bc7a5e464eedefd84f29 100644
--- a/lib/std/heap/PageAllocator.zig
+++ b/lib/std/heap/PageAllocator.zig
@@ -24,6 +24,7 @@ pub const vtable: Allocator.VTable = .{
 /// that don't provide a hint (for security reasons, but it serves our needs
 /// too).
 const enable_hints = switch (builtin.target.os.tag) {
+    .linux => !builtin.target.cpu.arch.isSPARC(), // https://bugzilla.kernel.org/show_bug.cgi?id=221820
     .openbsd => false,
     else => true,
 };
-- 
2.54.0


From 2085096f50fe235e9b6ddff8abc04daa4e5e7667 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 11:29:32 +0200
Subject: [PATCH 095/215] std.Thread: fix freeAndExit() on sparc[64]-linux
 hardware

On SPARC, the kernel needs to be able to restore the current register window
from the stack when returning from a syscall. That presents a bit of a problem
in freeAndExit() since we're deallocating the stack! The good news is that,
since we do not care about the contents of the incoming and local registers at
that point, we can just tell the kernel that our stack is an undefined global
buffer.

This didn't manifest in QEMU but does reproduce deterministically on a real
kernel/machine.
---
 lib/std/Thread.zig | 69 +++++++++++++++++++++-------------------------
 1 file changed, 32 insertions(+), 37 deletions(-)

diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 6eb76719a55d2787d04f124e58fa8829cbc7e8e9..05125adbe852a3586b4d77fa2d0f8f7dd4d4bb94 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -1146,6 +1146,13 @@ const LinuxThreadImpl = struct {
         parent_tid: i32 = undefined,
         mapped: []align(std.heap.page_size_min) u8,
 
+        // On SPARC, the kernel needs to be able to restore the current register window from the
+        // stack when returning from a syscall. That presents a bit of a problem in `freeAndExit`
+        // since we're deallocating the stack! The good news is that, since we do not care about
+        // the contents of the incoming and local registers at that point, we can just tell the
+        // kernel that our stack is this undefined global buffer.
+        var sparc_exit_stack: [192]u8 align(16) = undefined;
+
         /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`).
         /// Ported over from musl libc's pthread detached implementation:
         /// https://github.com/ifduyue/musl/search?q=__unmapself
@@ -1365,51 +1372,39 @@ const LinuxThreadImpl = struct {
                       [len] "{r5}" (self.mapped.len),
                 ),
                 .sparc => asm volatile (
-                    \\ # See sparc64 comments below.
-                    \\ 1:
-                    \\  cmp %%fp, 0
-                    \\  beq 2f
-                    \\  nop
-                    \\  ba 1b
-                    \\  restore
-                    \\ 2:
-                    \\  mov %%g1, %%o0 // ptr
-                    \\  mov %%g2, %%o1 // len
-                    \\  mov 73, %%g1 // SYS_munmap
-                    \\  t 0x3 // ST_FLUSH_WINDOWS
-                    \\  t 0x10
-                    \\  mov 1, %%g1 // SYS_exit
-                    \\  mov 0, %%o0
-                    \\  t 0x10
+                    \\ // See sparc64 comments below.
+                    \\ t 0x3 // ST_FLUSH_WINDOWS
+                    \\ mov %%g3, %%sp
+                    \\ mov %%g1, %%o0
+                    \\ mov %%g2, %%o1
+                    \\ mov 73, %%g1 // SYS_munmap
+                    \\ t 0x10
+                    \\ mov 1, %%g1 // SYS_exit
+                    \\ mov 0, %%o0
+                    \\ t 0x10
                     :
                     : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
                       [len] "{g2}" (self.mapped.len),
+                      [stack] "{g3}" (&sparc_exit_stack),
                     : .{ .memory = true }),
                 .sparc64 => asm volatile (
-                    \\ # SPARCs really don't like it when active stack frames
-                    \\ # is unmapped (it will result in a segfault), so we
-                    \\ # force-deactivate it by running `restore` until
-                    \\ # all frames are cleared.
-                    \\ 1:
-                    \\  cmp %%fp, 0
-                    \\  beq 2f
-                    \\  nop
-                    \\  ba 1b
-                    \\  restore
-                    \\ 2:
-                    \\  mov %%g1, %%o0 // ptr
-                    \\  mov %%g2, %%o1 // len
-                    \\  mov 73, %%g1 // SYS_munmap
-                    \\  # Flush register window contents to prevent background
-                    \\  # memory access before unmapping the stack.
-                    \\  flushw
-                    \\  t 0x6d
-                    \\  mov 1, %%g1 // SYS_exit
-                    \\  mov 0, %%o0
-                    \\  t 0x6d
+                    \\ // Ensure that the kernel only has to flush the current register window.
+                    \\ flushw
+                    \\ // Set up a fake stack for the syscall to restore l/i registers from. Local
+                    \\ // and incoming registers must be treated as effectively garbage past this
+                    \\ // instruction!
+                    \\ sub %%g3, 2047, %%sp
+                    \\ mov %%g1, %%o0
+                    \\ mov %%g2, %%o1
+                    \\ mov 73, %%g1 // SYS_munmap
+                    \\ t 0x6d
+                    \\ mov 1, %%g1 // SYS_exit
+                    \\ mov 0, %%o0
+                    \\ t 0x6d
                     :
                     : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)),
                       [len] "{g2}" (self.mapped.len),
+                      [stack] "{g3}" (&sparc_exit_stack),
                     : .{ .memory = true }),
                 .loongarch32, .loongarch64 => asm volatile (
                     \\ ori     $a7, $zero, 215     # SYS_munmap
-- 
2.54.0


From eda296c24a80f15b4f28b985fa7ff782bb6b731e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 14:15:08 +0200
Subject: [PATCH 096/215] std.os.linux: fix restore_rt() on sparc/sparc64

Not really sure what this function was trying to do before, but it seems kind of
nonsensical. All it needs to do is perform an rt_sigreturn syscall, with the
gotcha that it needs two nop instructions at the beginning to accommodate the
way that ret instructions are done in the SPARC ABI (%i7 + 8 to skip the call
instruction and delay slot). The callconv(.c) is certainly not necessary and
probably caused bugs on its own.
---
 lib/std/os/linux/sparc.zig   | 13 ++++++++-----
 lib/std/os/linux/sparc64.zig | 13 ++++++++-----
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/lib/std/os/linux/sparc.zig b/lib/std/os/linux/sparc.zig
index 4a2e7188a6b2a9cf582edddf204ce8fc61d4fb95..c8addd36c45bfc08aff71672c2aeef42bb948f06 100644
--- a/lib/std/os/linux/sparc.zig
+++ b/lib/std/os/linux/sparc.zig
@@ -260,13 +260,16 @@ pub fn clone() callconv(.naked) u32 {
 
 pub const restore = restore_rt;
 
-// Need to use C ABI here instead of naked
-// to prevent an infinite loop when calling rt_sigreturn.
-pub fn restore_rt() callconv(.c) void {
-    return asm volatile ("t 0x10"
+pub fn restore_rt() callconv(.naked) noreturn {
+    asm volatile (
+        \\ nop
+        \\ nop
+    );
+    asm volatile (
+        \\ t 0x10
         :
         : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
-        : .{ .memory = true, .xcc = true, .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
+    );
 }
 
 pub const VDSO = struct {
diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig
index f7e859cc72abfe37dfee1f5ab5927979c2625615..955ae477c3f81d1f190ad7cb440108747cff9b56 100644
--- a/lib/std/os/linux/sparc64.zig
+++ b/lib/std/os/linux/sparc64.zig
@@ -259,13 +259,16 @@ pub fn clone() callconv(.naked) u64 {
 
 pub const restore = restore_rt;
 
-// Need to use C ABI here instead of naked
-// to prevent an infinite loop when calling rt_sigreturn.
-pub fn restore_rt() callconv(.c) void {
-    return asm volatile ("t 0x6d"
+pub fn restore_rt() callconv(.naked) noreturn {
+    asm volatile (
+        \\ nop
+        \\ nop
+    );
+    asm volatile (
+        \\ t 0x6d
         :
         : [number] "{g1}" (@backingInt(SYS.rt_sigreturn)),
-        : .{ .memory = true, .xcc = true, .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o7 = true });
+    );
 }
 
 pub const VDSO = struct {
-- 
2.54.0


From c089dd22a97c55f36bcdcf962d646bd67cc33fb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 14:33:08 +0200
Subject: [PATCH 097/215] Revert "std: disable some failing cancelation tests
 on sparc64-linux"

This reverts commit 3b330f1d7c36416924f8986a6c541331130297d4.
---
 lib/std/Io/Threaded/test.zig | 2 --
 lib/std/Io/net/test.zig      | 2 --
 lib/std/Io/test.zig          | 2 --
 3 files changed, 6 deletions(-)

diff --git a/lib/std/Io/Threaded/test.zig b/lib/std/Io/Threaded/test.zig
index bb49dbc1b5fbc2e502c0368756d838c39a2e0258..392323de9b15c8674b4af0ea7aea21a5f49d6faf 100644
--- a/lib/std/Io/Threaded/test.zig
+++ b/lib/std/Io/Threaded/test.zig
@@ -149,8 +149,6 @@ test "async with array return type" {
 }
 
 test "cancel blocked read from pipe" {
-    if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
-
     const global = struct {
         fn readFromPipe(io: Io, pipe: Io.File) !void {
             var buf: [1]u8 = undefined;
diff --git a/lib/std/Io/net/test.zig b/lib/std/Io/net/test.zig
index 308dc1a32670e207e72511d0128b634972050e6a..12fa0a846c0b6576e0f0b593bc51290e6f086b14 100644
--- a/lib/std/Io/net/test.zig
+++ b/lib/std/Io/net/test.zig
@@ -356,8 +356,6 @@ test "decompress compressed DNS name" {
 }
 
 test "cancel accept" {
-    if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
-
     const io = testing.io;
     const localhost: net.IpAddress = .{ .ip4 = .loopback(0) };
 
diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig
index 3d9523da7675c01e8a780e139e886231f1e04617..0874553c9f42656e14fafffbf0c26aee2d271f41 100644
--- a/lib/std/Io/test.zig
+++ b/lib/std/Io/test.zig
@@ -326,8 +326,6 @@ test "Group materializes error.Cancel" {
 }
 
 test "Group task receives cancelation unknowingly" {
-    if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
-
     const S = struct {
         io: Io,
         err: ?Io.Cancelable!void,
-- 
2.54.0


From b6810db40a18026e0362ef04570468a6a3a89635 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 14:31:50 +0200
Subject: [PATCH 098/215] Revert "std.Io.RwLock: disable `lock canceling` test
 on SPARC"

This reverts commit fe6c3e58ef11c8377ce4adfc89301bf4edaf42ab.
---
 lib/std/Io/RwLock.zig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/std/Io/RwLock.zig b/lib/std/Io/RwLock.zig
index 7a445033db6b50da7ab31ee8a6cb7b7f6c3ed438..de9bf86f366314f64ed45877c675dd2cbd9eee4a 100644
--- a/lib/std/Io/RwLock.zig
+++ b/lib/std/Io/RwLock.zig
@@ -284,8 +284,6 @@ test "concurrent access" {
 }
 
 test "lock canceling" {
-    if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
-
     const io = testing.io;
 
     var rl: Io.RwLock = .init;
-- 
2.54.0


From bcf65eb51085c0fa1a9380172cdea55811d9fe97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 14:31:08 +0200
Subject: [PATCH 099/215] Revert "std.Io: disable `Group.cancel` on
 sparc64-linux"

This reverts commit ef3040786e502ea82e87ffefb9570b4e88dff79b.
---
 lib/std/Io/test.zig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/std/Io/test.zig b/lib/std/Io/test.zig
index 0874553c9f42656e14fafffbf0c26aee2d271f41..54d79fceec8e6adebbc4e35867bcea93aa318bf2 100644
--- a/lib/std/Io/test.zig
+++ b/lib/std/Io/test.zig
@@ -232,8 +232,6 @@ fn count(a: usize, b: usize, result: *usize) void {
 }
 
 test "Group.cancel" {
-    if (builtin.cpu.arch.isSPARC() and builtin.os.tag == .linux) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35347
-
     const global = struct {
         fn sleep(io: Io, result: *usize) Io.Cancelable!void {
             defer result.* = 1;
-- 
2.54.0


From 6ee0ef96fea84f66ad3e7e987a07a5b89ab41308 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 1 Aug 2026 19:13:10 +0200
Subject: [PATCH 100/215] build: bump max_rss of test-unit to 3_000_000_000

error: memory usage peaked at 2.74GB (2744430592 bytes), exceeding the declared upper bound of 2.70GB (2700000000 bytes)
---
 build.zig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build.zig b/build.zig
index 74ef42a775985c90dd8a5b6b80a0926e4bc6012b..3c019d38171015207279d3fd6a535e77ea99f6b0 100644
--- a/build.zig
+++ b/build.zig
@@ -622,7 +622,7 @@ pub fn build(b: *std.Build) !void {
         .use_llvm = use_llvm,
         .use_lld = use_llvm,
         .zig_lib_dir = b.path("lib"),
-        .max_rss = 2_700_000_000,
+        .max_rss = 3_000_000_000,
     });
     if (link_libc) {
         unit_tests.root_module.link_libc = true;
-- 
2.54.0


From 9ef236bc114fa859768d0837abe4e7e573ad22c8 Mon Sep 17 00:00:00 2001
From: whatisaphone 
Date: Fri, 31 Jul 2026 17:24:16 -0400
Subject: [PATCH 101/215] Add env var to set zig build --summary

---
 lib/compiler/Maker.zig | 6 ++++++
 lib/std/zig.zig        | 1 +
 2 files changed, 7 insertions(+)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index b5db0e68f7597a1e951900e8b741afb20521bcda..ade19eeb33a672846fb80709ff26089cbb883fac 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -242,6 +242,12 @@ pub fn main(init: process.Init.Minimal) !void {
         }
     }
 
+    if (EnvVar.ZIG_BUILD_SUMMARY.get(&graph.environ_map)) |str| {
+        if (stringToEnum(Summary, str)) |value| {
+            summary = value;
+        }
+    }
+
     try configure_argv.ensureUnusedCapacity(arena, 16);
     try cached_passthru_configure.ensureUnusedCapacity(arena, 16);
 
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
index 4c41d56845f7ebd32bb83a51d2ec182b7e4e7154..858fb169439c2cdffa31f200e650e7151a2da991 100644
--- a/lib/std/zig.zig
+++ b/lib/std/zig.zig
@@ -763,6 +763,7 @@ pub const EnvVar = enum {
     ZIG_LIBC,
     ZIG_BUILD_ERROR_STYLE,
     ZIG_BUILD_MULTILINE_ERRORS,
+    ZIG_BUILD_SUMMARY,
     ZIG_VERBOSE_LINK,
     ZIG_VERBOSE_CC,
     ZIG_VERBOSE_CMD,
-- 
2.54.0


From 47c5f556c08c1b15c74dbaca743d17a3297bcdef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Igor=20Anic=CC=81?= 
Date: Sat, 1 Aug 2026 13:41:45 +0200
Subject: [PATCH 102/215] Io.Uring: fix dir.hardLink

Unsupported flags is used resulting in invalid arguments:
```Zig
thread 556130 panic: programmer bug caused syscall error: INVAL
.../lib/std/Io/Threaded.zig:14258:34: 0x116f3fa in errnoBug (std.zig)
    if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err});
                                 ^
.../lib/std/Io/Uring.zig:5583:44: 0x1281981 in linkat (std.zig)
            .INVAL => |err| return errnoBug(err),
                                           ^
.../lib/std/Io/Uring.zig:3555:21: 0x1289ab9 in dirHardLink (std.zig)
    return ev.linkat(```
```

```Zig
test "linkat" {
    const gpa = testing.allocator;

    var uring: Io.Uring = undefined;
    try uring.init(gpa, .{});
    defer uring.deinit();

    var threaded = Io.Threaded.init(gpa, .{});
    defer threaded.deinit();

    for ([_]Io{ threaded.io(), uring.io() }) |io| {
        var tmp = testing.tmpDir(.{});
        defer tmp.cleanup();
        const dir = tmp.dir;

        const dir2 = try dir.createDirPathOpen(io, "folder/sub_folder", .{});
        defer dir2.close(io);

        const file = try dir.createFile(io, "file", .{});
        defer file.close(io);
        try dir.hardLink("file", dir2, "link", io, .{});
        try file.hardLink(io, dir2, "link2", .{});

        var stat = try dir.statFile(io, "folder/sub_folder/link", .{});
        try testing.expectEqual(.file, stat.kind);
        stat = try dir.statFile(io, "folder/sub_folder/link2", .{});
        try testing.expectEqual(.file, stat.kind);
    }
}
```
---
 lib/std/Io/Uring.zig | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig
index 58d97dc0e8e090c84bec204f74be93a8bd5e5c37..6edf381378148e64941e64559150f77ad94a0650 100644
--- a/lib/std/Io/Uring.zig
+++ b/lib/std/Io/Uring.zig
@@ -3561,7 +3561,7 @@ fn dirHardLink(
         old_sub_path_posix,
         new_dir.handle,
         new_sub_path_posix,
-        if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW,
+        if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0,
     );
 }
 
@@ -3993,7 +3993,7 @@ fn fileHardLink(
         "",
         new_dir.handle,
         new_sub_path_posix,
-        linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW),
+        linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0),
     );
 }
 
@@ -5545,6 +5545,8 @@ fn linkat(
     new_path: [*:0]const u8,
     flags: u32,
 ) File.HardLinkError!void {
+    // allowed flags: https://man7.org/linux/man-pages/man2/linkat.2.html
+    assert(flags & ~(@as(u32, linux.AT.SYMLINK_FOLLOW | linux.AT.EMPTY_PATH)) == 0);
     while (true) {
         const thread = try cancel_region.awaitIoUring();
         thread.enqueue().* = .{
-- 
2.54.0


From 6db520a4cd1ce2391c79d0d55b2b2d5297e133a3 Mon Sep 17 00:00:00 2001
From: Pavel Verigo 
Date: Fri, 31 Jul 2026 02:28:42 +0200
Subject: [PATCH 103/215] stage2-wasm: pass cabi tests

- make ubsan to be linkable by linker
- currently ignore bool vectors tests for `.stage2_wasm`, let defer handling it properly after supporting simd128 in backend (mainly tiny fixes + enabling it for matrix)
- I needed to refactor `wasm/abi.zig`, still bad
---
 src/codegen/llvm/FuncGen.zig |   4 +-
 src/codegen/wasm/CodeGen.zig | 113 +++++++++++++++++++++++++----------
 src/codegen/wasm/abi.zig     |  46 ++++++++++----
 src/link/Wasm.zig            |  35 +++++++----
 src/link/Wasm/Flush.zig      |  37 ++++++++++--
 src/link/Wasm/Object.zig     |   2 +-
 src/target.zig               |   2 +-
 test/c_abi/main.zig          |  18 ++++++
 test/tests.zig               |   9 +++
 9 files changed, 202 insertions(+), 64 deletions(-)

diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig
index 2bdd059f1fe217c8675e5faa9acead19208c2cf3..676fad2f1036445d01e1774b223e1af849d01f82 100644
--- a/src/codegen/llvm/FuncGen.zig
+++ b/src/codegen/llvm/FuncGen.zig
@@ -7156,7 +7156,7 @@ const ParamTypeIterator = struct {
                     },
                 }
             },
-            .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) {
+            .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ty, zcu)) {
                 .direct => |scalar_ty| {
                     if (isScalar(zcu, ty)) {
                         it.zig_index += 1;
@@ -7508,7 +7508,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A
             .simple_aggregate => unreachable,
             .pointer => .sret,
         },
-        .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) {
+        .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ret_ty, zcu)) {
             .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
                 assert(!isByRef(ret_ty, zcu));
                 return .by_val;
diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig
index 8d6e18385f8de67b92f5ba72cde959fc6df83b91..8b9b5869d85fcf498847c2fe49fb72dd7fa6232a 100644
--- a/src/codegen/wasm/CodeGen.zig
+++ b/src/codegen/wasm/CodeGen.zig
@@ -927,21 +927,26 @@ fn resolveCallingConventionValues(
         },
         .wasm_mvp => {
             for (fn_info.param_types.get(ip)) |ty| {
-                if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) {
+                const param_ty: Type = .fromInterned(ty);
+                if (!param_ty.hasRuntimeBits(zcu)) {
                     continue;
                 }
-                switch (abi.classifyType(.fromInterned(ty), zcu)) {
-                    .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
+
+                switch (abi.classifyType(param_ty, zcu, target)) {
+                    .direct, .indirect => {
                         try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
                         result.local_index += 1;
-                    } else {
+                    },
+                    .double_i64 => {
                         try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
                         try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } });
                         result.local_index += 2;
                     },
-                    .indirect => {
-                        try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
-                        result.local_index += 1;
+                    .unrolled => |vector| {
+                        for (0..vector.len) |_| {
+                            try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
+                            result.local_index += 1;
+                        }
                     },
                 }
             }
@@ -968,9 +973,10 @@ pub fn firstParamSRet(
     switch (cc) {
         .@"inline" => unreachable,
         .auto => return isByRef(return_type, zcu, target),
-        .wasm_mvp => switch (abi.classifyType(return_type, zcu)) {
-            .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu),
-            .indirect => return true,
+        .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) {
+            .direct => return false,
+            .double_i64, .indirect => return true,
+            .unrolled => |vector| return vector.len > 1,
         },
         else => return false,
     }
@@ -985,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
 
     const zcu = cg.pt.zcu;
 
-    switch (abi.classifyType(ty, zcu)) {
-        .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) {
+    switch (abi.classifyType(ty, zcu, cg.target)) {
+        .direct => |scalar_ty| {
             if (!isByRef(ty, zcu, cg.target)) {
                 return cg.lowerToStack(value);
             } else {
-                switch (value) {
-                    .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0),
-                    .dead => unreachable,
-                    else => try cg.emitWValue(value),
-                }
+                _ = try cg.load(value, scalar_ty, 0);
             }
-        } else {
+        },
+        .double_i64 => {
             assert(ty.abiSize(zcu) == 16);
             // in this case we have an integer or float that must be lowered as 2 i64's.
             try cg.emitWValue(value);
@@ -1004,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
             try cg.emitWValue(value);
             try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });
         },
-        .indirect => return cg.lowerToStack(value),
+        .indirect => {
+            const stack_copy = try cg.allocStack(ty);
+            try cg.store(stack_copy, value, ty, 0);
+            return cg.lowerToStack(stack_copy);
+        },
+        .unrolled => |vector| {
+            const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
+            for (0..vector.len) |index| {
+                _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size));
+            }
+        },
     }
 }
 
@@ -1947,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
     if (cg.return_value != .none) {
         try cg.store(cg.return_value, operand, ret_ty, 0);
     } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) {
-        switch (abi.classifyType(ret_ty, zcu)) {
+        switch (abi.classifyType(ret_ty, zcu, cg.target)) {
             .direct => |scalar_type| {
-                assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
                 if (!isByRef(ret_ty, zcu, cg.target)) {
                     try cg.emitWValue(operand);
                 } else {
                     _ = try cg.load(operand, scalar_type, 0);
                 }
             },
-            .indirect => unreachable,
+            .double_i64, .indirect => unreachable,
+            .unrolled => |vector| {
+                assert(vector.len == 1);
+                _ = try cg.load(operand, vector.elem_type, 0);
+            },
         }
     } else {
         if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) {
@@ -2003,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
             try cg.addImm32(0);
         }
     } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {
-        // leave on the stack
-        _ = try cg.load(operand, ret_ty, 0);
+        if (fn_info.cc == .wasm_mvp) {
+            switch (abi.classifyType(ret_ty, zcu, cg.target)) {
+                .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0),
+                .double_i64, .indirect => unreachable,
+                .unrolled => |vector| {
+                    assert(vector.len == 1);
+                    _ = try cg.load(operand, vector.elem_type, 0);
+                },
+            }
+        } else {
+            _ = try cg.load(operand, ret_ty, 0);
+        }
     }
 
     try cg.restoreStackPointer();
@@ -2132,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
         } else if (first_param_sret) {
             break :result_value sret;
         } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) {
-            switch (abi.classifyType(ret_ty, zcu)) {
+            switch (abi.classifyType(ret_ty, zcu, cg.target)) {
                 .direct => |scalar_type| {
-                    assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
                     if (!isByRef(ret_ty, zcu, cg.target)) {
                         const result_local = try cg.allocLocal(ret_ty);
                         try cg.addLocal(.local_set, result_local.local.value);
                         break :result_value result_local;
                     } else {
-                        const result_local = try cg.allocLocal(ret_ty);
+                        const result_local = try cg.allocLocal(scalar_type);
                         try cg.addLocal(.local_set, result_local.local.value);
                         const result = try cg.allocStack(ret_ty);
                         try cg.store(result, result_local, scalar_type, 0);
                         break :result_value result;
                     }
                 },
-                .indirect => unreachable,
+                .double_i64, .indirect => unreachable,
+                .unrolled => |vector| {
+                    assert(vector.len == 1);
+                    const result_local = try cg.allocLocal(vector.elem_type);
+                    // save call result from operand stack
+                    try cg.addLocal(.local_set, result_local.local.value);
+                    const result = try cg.allocStack(ret_ty);
+                    try cg.store(result, result_local, vector.elem_type, 0);
+                    break :result_value result;
+                },
             }
         } else {
             const result_local = try cg.allocLocal(ret_ty);
@@ -2450,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
     const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc;
     const arg_ty = cg.typeOfIndex(inst);
     if (cc == .wasm_mvp) {
-        switch (abi.classifyType(arg_ty, zcu)) {
-            .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
+        switch (abi.classifyType(arg_ty, zcu, cg.target)) {
+            .direct => |scalar_type| {
                 cg.arg_index += 1;
-            } else {
+                if (isByRef(arg_ty, zcu, cg.target)) {
+                    const result = try cg.allocStack(arg_ty);
+                    try cg.store(result, arg, scalar_type, 0);
+                    return cg.finishAir(inst, result, &.{});
+                }
+            },
+            .indirect => cg.arg_index += 1,
+            .double_i64 => {
                 cg.arg_index += 2;
                 const result = try cg.allocStack(arg_ty);
                 try cg.store(result, arg, Type.u64, 0);
                 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);
                 return cg.finishAir(inst, result, &.{});
             },
-            .indirect => cg.arg_index += 1,
+            .unrolled => |vector| {
+                const result = try cg.allocStack(arg_ty);
+                const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
+                for (0..vector.len) |index| {
+                    try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size));
+                    cg.arg_index += 1;
+                }
+                return cg.finishAir(inst, result, &.{});
+            },
         }
     } else {
         cg.arg_index += 1;
diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig
index 244b2c7719476ffa1542ce5863c11ac62c3c36de..0c6afdcc500202b4b4dd4b794d28b9fdb813af70 100644
--- a/src/codegen/wasm/abi.zig
+++ b/src/codegen/wasm/abi.zig
@@ -11,16 +11,44 @@ const assert = std.debug.assert;
 const Type = @import("../../Type.zig");
 const Zcu = @import("../../Zcu.zig");
 
-/// Defines how to pass a type as part of a function signature,
-/// both for parameters as well as return values.
+/// Describes how the Wasm backend represents a C ABI value.
 pub const Class = union(enum) {
     direct: Type,
+    double_i64,
     indirect,
+    unrolled: struct {
+        elem_type: Type,
+        len: u32,
+    },
 };
 
-/// Classifies a given Zig type to determine how they must be passed
-/// or returned as value within a wasm function.
-pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
+pub const LlvmClass = union(enum) {
+    direct: Type,
+    indirect,
+};
+
+pub fn classifyType(ty: Type, zcu: *const Zcu, target: *const Target) Class {
+    if (ty.zigTypeTag(zcu) == .vector) {
+        if (!(ty.bitSize(zcu) == 128 and target.cpu.has(.wasm, .simd128))) {
+            const elem_type = ty.childType(zcu);
+            return .{ .unrolled = .{
+                .elem_type = elem_type,
+                .len = ty.vectorLen(zcu),
+            } };
+        }
+        return .{ .direct = ty };
+    }
+
+    return switch (classifyTypeForLlvm(ty, zcu)) {
+        .direct => |scalar_ty| if (scalar_ty.bitSize(zcu) > 64)
+            .double_i64
+        else
+            .{ .direct = scalar_ty },
+        .indirect => .indirect,
+    };
+}
+
+pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
     const ip = &zcu.intern_pool;
     assert(ty.hasRuntimeBits(zcu));
     switch (ty.zigTypeTag(zcu)) {
@@ -56,7 +84,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
                 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
                     return .indirect;
             }
-            return classifyType(field_ty, zcu);
+            return classifyTypeForLlvm(field_ty, zcu);
         },
         .@"union" => {
             const union_obj = zcu.typeToUnion(ty).?;
@@ -67,7 +95,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
             assert(layout.tag_size == 0);
             if (union_obj.field_types.len > 1) return .indirect;
             const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
-            return classifyType(first_field_ty, zcu);
+            return classifyTypeForLlvm(first_field_ty, zcu);
         },
         .error_union,
         .frame,
@@ -86,7 +114,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
         => unreachable,
     }
 }
-
-pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool {
-    return scalar_ty.bitSize(zcu) > 64;
-}
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 352448fd38a62533f708e3be5331cdf96aa91fa5..495b9d06603191ca2b503e98f413b9ab3ead52d9 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -4938,12 +4938,15 @@ fn convertZcuFnType(
         try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle
     } else if (return_type.hasRuntimeBits(zcu)) {
         if (cc == .wasm_mvp) {
-            switch (abi.classifyType(return_type, zcu)) {
-                .direct => |scalar_ty| {
-                    assert(!abi.lowerAsDoubleI64(scalar_ty, zcu));
-                    try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
+            switch (abi.classifyType(return_type, zcu, target)) {
+                .direct => |scalar_type| {
+                    try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
+                },
+                .double_i64, .indirect => unreachable,
+                .unrolled => |vector| {
+                    assert(vector.len == 1);
+                    try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
                 },
-                .indirect => unreachable,
             }
         } else {
             try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target));
@@ -4959,16 +4962,22 @@ fn convertZcuFnType(
 
         switch (cc) {
             .wasm_mvp => {
-                switch (abi.classifyType(param_type, zcu)) {
-                    .direct => |scalar_ty| {
-                        if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
-                            try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
-                        } else {
-                            try params_buffer.append(gpa, .i64);
-                            try params_buffer.append(gpa, .i64);
+                switch (abi.classifyType(param_type, zcu, target)) {
+                    .direct => |scalar_type| {
+                        try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
+                    },
+                    .double_i64 => {
+                        try params_buffer.append(gpa, .i64);
+                        try params_buffer.append(gpa, .i64);
+                    },
+                    .indirect => {
+                        try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target));
+                    },
+                    .unrolled => |vector| {
+                        for (0..vector.len) |_| {
+                            try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
                         }
                     },
-                    .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
                 }
             },
             else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig
index 45633149611c318bb5623d6cbb5ba75bcab77f5a..9c15adf65029f90fd95b13f57599bc9bcb6f9bcf 100644
--- a/src/link/Wasm/Flush.zig
+++ b/src/link/Wasm/Flush.zig
@@ -248,6 +248,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
 
     if (comp.zcu) |zcu| {
         const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!
+        const function_imports_start = wasm.function_imports.entries.len;
+        const global_imports_start = wasm.global_imports.entries.len;
+        const data_imports_start = wasm.data_imports.entries.len;
 
         log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len});
 
@@ -464,6 +467,35 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
             else => continue,
         };
 
+        // marking above may discover additional imports
+        try f.function_imports.ensureUnusedCapacity(gpa, wasm.function_imports.entries.len - function_imports_start);
+        for (
+            wasm.function_imports.keys()[function_imports_start..],
+            wasm.function_imports.values()[function_imports_start..],
+        ) |name, id| {
+            if (!f.function_imports.contains(name) and Wasm.FunctionIndex.fromSymbolName(wasm, name) == null) {
+                f.function_imports.putAssumeCapacity(name, id);
+            }
+        }
+
+        try f.global_imports.ensureUnusedCapacity(gpa, wasm.global_imports.entries.len - global_imports_start);
+        for (
+            wasm.global_imports.keys()[global_imports_start..],
+            wasm.global_imports.values()[global_imports_start..],
+        ) |name, id| {
+            if (!f.global_imports.contains(name)) f.global_imports.putAssumeCapacity(name, id);
+        }
+
+        try f.data_imports.ensureUnusedCapacity(gpa, wasm.data_imports.entries.len - data_imports_start);
+        for (
+            wasm.data_imports.keys()[data_imports_start..],
+            wasm.data_imports.values()[data_imports_start..],
+        ) |name, id| {
+            if (!f.data_imports.contains(name) and !f.data_exports.contains(name)) {
+                f.data_imports.putAssumeCapacity(name, id);
+            }
+        }
+
         for (f.missing_exports.keys()) |exp_name| {
             diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)});
         }
@@ -1075,13 +1107,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
     if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {
         try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index))));
         section_index += 1;
-    } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {
-        try emitStartSection(gpa, binary_bytes, func_index);
-        section_index += 1;
     }
 
     // element section
-    if (f.indirect_function_table.entries.len > 0) {
+    if (!is_obj and f.indirect_function_table.entries.len > 0) {
         const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
 
         // indirect function table elements
diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig
index 44359b315bdec094029d9ceed782f798ea32f25f..dbd02289d66cd40ce3e5c43d7cb6ff99f9570dd2 100644
--- a/src/link/Wasm/Object.zig
+++ b/src/link/Wasm/Object.zig
@@ -856,7 +856,7 @@ pub fn parse(
                 start_function = @fromBackingInt(@intCast(functions_start + index));
             },
             .element => {
-                log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name });
+                // element section is not needed for linking, validating it serves no purpose
                 pos = section_end;
             },
             .code => {
diff --git a/src/target.zig b/src/target.zig
index 82728f3942f07da8fe6d64c922c69a91e8e7ae66..00a7e498d95fba989875fb9c96aa93273c51ac58 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -450,7 +450,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,
         else => {},
     }
     return switch (zigBackend(target, false)) {
-        .stage2_wasm => .llvm_lld_only,
+        .stage2_wasm => .yes,
         .stage2_x86_64 => .yes,
         else => .llvm_only,
     };
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index a80bacd7ae3d5659902e670ebd38386ecd8c0928..1fd267402d74dbb38e524c8e232240ff97ef5217 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -451,6 +451,7 @@ test "long double" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -477,6 +478,7 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;
 extern fn c_test_vector_2_bool() void;
 
 test "@Vector(2, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
@@ -497,6 +499,7 @@ test "@Vector(2, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -527,6 +530,7 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;
 extern fn c_test_vector_4_bool() void;
 
 test "@Vector(4, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
@@ -551,6 +555,7 @@ test "@Vector(4, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -589,6 +594,7 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;
 extern fn c_test_vector_8_bool() void;
 
 test "@Vector(8, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
@@ -621,6 +627,7 @@ test "@Vector(8, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -675,6 +682,7 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;
 extern fn c_test_vector_16_bool() void;
 
 test "@Vector(16, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
@@ -723,6 +731,7 @@ test "@Vector(16, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -809,6 +818,7 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;
 extern fn c_test_vector_32_bool() void;
 
 test "@Vector(32, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
@@ -889,6 +899,7 @@ test "@Vector(32, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -1039,6 +1050,7 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;
 extern fn c_test_vector_64_bool() void;
 
 test "@Vector(64, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
     if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
     if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
@@ -1181,6 +1193,7 @@ test "@Vector(64, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -1459,6 +1472,7 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;
 extern fn c_test_vector_128_bool() void;
 
 test "@Vector(128, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
     if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
     if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
@@ -1729,6 +1743,7 @@ test "@Vector(128, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -2263,6 +2278,7 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;
 extern fn c_test_vector_256_bool() void;
 
 test "@Vector(256, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
     if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
     if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
@@ -2789,6 +2805,7 @@ test "@Vector(256, bool)" {
 
 comptime {
     skip: {
+        if (builtin.zig_backend == .stage2_wasm) break :skip;
         if (builtin.cpu.arch == .hexagon) break :skip;
         if (builtin.cpu.arch == .loongarch64) break :skip;
         if (builtin.cpu.arch.isMIPS()) break :skip;
@@ -3835,6 +3852,7 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;
 extern fn c_test_vector_512_bool() void;
 
 test "@Vector(512, bool)" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
     if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
     if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
diff --git a/test/tests.zig b/test/tests.zig
index 390154d8fc4cd3f1a9b30fdba87da448d6cbd0e0..90442edf52c9135eaf901c075828191cae6e45f3 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -2060,6 +2060,15 @@ const c_abi_targets = blk: {
                 .abi = .musl,
             },
         },
+        .{
+            .target = .{
+                .cpu_arch = .wasm32,
+                .os_tag = .wasi,
+                .abi = .musl,
+            },
+            .use_llvm = false,
+            .use_lld = false,
+        },
 
         // Windows Targets
 
-- 
2.54.0


From 8523ee09ae1f03d93d8029263c7bb7fe0ec282e7 Mon Sep 17 00:00:00 2001
From: Bernard Assan 
Date: Mon, 29 Jun 2026 19:43:51 +0000
Subject: [PATCH 104/215] Implement Meson ConfigHeader support

updated PR for the new build system changes

add standalone tests for meson config_header

Signed-off-by: Bernard Assan 
---
 lib/compiler/Maker/Step/ConfigHeader.zig      | 137 ++++++++++++++++++
 lib/std/Build/Configuration.zig               |   2 +
 lib/std/Build/Step/ConfigHeader.zig           |   5 +-
 test/standalone/config_header/build.zig       |  21 +++
 .../config_header/meson/mesondefine.h         |  22 +++
 .../config_header/meson/mesondefine.h.in      |  21 +++
 6 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 test/standalone/config_header/meson/mesondefine.h
 create mode 100644 test/standalone/config_header/meson/mesondefine.h.in

diff --git a/lib/compiler/Maker/Step/ConfigHeader.zig b/lib/compiler/Maker/Step/ConfigHeader.zig
index 2863ced63f5f96def9a22d8870f35e999a021a7f..20152955fe469b751648032e54152a7aa2b53f67 100644
--- a/lib/compiler/Maker/Step/ConfigHeader.zig
+++ b/lib/compiler/Maker/Step/ConfigHeader.zig
@@ -93,6 +93,32 @@ pub fn make(
                 else => |e| return e,
             };
         },
+        .meson => {
+            const tf = template_file.?;
+            const contents = tf.root_dir.handle.readFileAlloc(
+                io,
+                tf.sub_path,
+                arena,
+                input_size_limit,
+            ) catch |err| return step.fail(
+                maker,
+                "unable to read meson input file {f}: {t}",
+                .{ tf, err },
+            );
+
+            renderMeson(
+                maker,
+                step,
+                contents,
+                &aw,
+                value_pairs,
+                &value_map,
+                tf,
+            ) catch |err| switch (err) {
+                error.WriteFailed => return error.OutOfMemory,
+                else => |e| return e,
+            };
+        },
         .blank => {
             renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) {
                 error.WriteFailed => return error.OutOfMemory,
@@ -370,6 +396,62 @@ fn renderCmake(
     if (any_errors) return error.MakeFailed;
 }
 
+fn renderMeson(
+    maker: *Maker,
+    step: *Step,
+    contents: []const u8,
+    aw: *Writer.Allocating,
+    value_pairs: []const Value.Pair,
+    value_map: *const ValueMap,
+    src_path: Path,
+) !void {
+    const w = &aw.writer;
+    const conf = &maker.scanned_config.configuration;
+    const newline = detectNewline(contents);
+
+    try w.writeAll(c_generated_line);
+    try w.writeAll(newline);
+
+    var any_errors = false;
+    var line_index: u32 = 0;
+    var line_it = std.mem.splitScalar(u8, contents, '\n');
+    // https://mesonbuild.com/Configuration.html
+    while (line_it.next()) |raw_line| : (line_index += 1) {
+        const last_line = line_it.index == line_it.buffer.len;
+        const line = std.mem.trimEnd(u8, raw_line, "\r");
+
+        const old_len = aw.written().len;
+        expandVariablesMeson(w, conf, line, value_pairs, value_map) catch |err| switch (err) {
+            error.MissingToken => {
+                try step.addError(maker, "{f}:{d}: error: missing define name", .{ src_path, line_index + 1 });
+                any_errors = true;
+                continue;
+            },
+            error.MissingValue => {
+                const name = aw.written()[old_len..];
+                defer aw.shrinkRetainingCapacity(old_len);
+
+                try step.addError(maker, "{f}:{d}: error: unspecified config header value: {q}", .{
+                    src_path, line_index + 1, name,
+                });
+                any_errors = true;
+                continue;
+            },
+            else => {
+                try step.addError(maker, "{f}:{d}: unable to substitute variable: error: {t}", .{
+                    src_path, line_index + 1, err,
+                });
+                any_errors = true;
+                continue;
+            },
+        };
+        if (!last_line) try w.writeAll(newline);
+    }
+
+    try ensureAllValuesUsed(maker, step, value_map, src_path);
+    if (any_errors) return error.MakeFailed;
+}
+
 fn renderBlank(
     conf: *const Configuration,
     w: *Writer,
@@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam
     }
 }
 
+fn renderValueMeson(
+    conf: *const Configuration,
+    w: *Writer,
+    name: []const u8,
+    value: Value.Index,
+) !void {
+    switch (value.unpack(conf)) {
+        .undef => try w.print("/* #undef {s} */", .{name}),
+        .defined => try w.print("#define {s}", .{name}),
+        .bool => |b| {
+            if (b) {
+                try w.print("#define {s}", .{name});
+            } else {
+                try w.print("#undef {s}", .{name});
+            }
+        },
+        inline .u64, .i64 => |int| try w.print("#define {s} {d}", .{ name, int }),
+        .ident => |ident| try w.print("#define {s} {s}", .{ name, ident }),
+        .string => |string| try w.print("#define {s} \"{f}\"", .{ name, std.zig.fmtString(string) }),
+    }
+}
+
 fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {
     try w.print("#define {s}", .{name});
     if (ident.len > 0) {
@@ -628,3 +732,36 @@ fn expandVariablesCmake(
 
     return result.toOwnedSliceAssert();
 }
+
+fn expandVariablesMeson(
+    w: *Writer,
+    conf: *const Configuration,
+    line: []const u8,
+    value_pairs: []const Value.Pair,
+    value_map: *const ValueMap,
+) !void {
+    const mesondefine = "#mesondefine";
+    if (std.mem.startsWith(u8, line, mesondefine)) {
+        const line_offset = mesondefine.len + 1;
+        if (line_offset > line.len) return error.MissingToken;
+
+        var it = std.mem.tokenizeAny(u8, line[line_offset..], " \t\r");
+        const name = it.next() orelse return error.MissingToken;
+
+        const index = value_map.getIndex(name) orelse {
+            // Report the missing key to the caller.
+            try w.writeAll(name);
+            return error.MissingValue;
+        };
+
+        const value = value_pairs[index].index;
+        value_map.values()[index] = true; // Mark as used.
+
+        try renderValueMeson(conf, w, name, value);
+
+        // comments/any other text passthrough unaffected
+        return try w.writeAll(line[line_offset + name.len ..]);
+    }
+
+    try expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map);
+}
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index 31da18abfd88368efb7ded2112d3343bdcf6201a..b04a7c592460b1db60c80b412edcbf973c5d29e2 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -1076,6 +1076,7 @@ pub const Step = extern struct {
             autoconf_undef,
             autoconf_at,
             cmake,
+            meson,
             blank,
             nasm,
 
@@ -1084,6 +1085,7 @@ pub const Step = extern struct {
                     .autoconf_undef => .autoconf_undef,
                     .autoconf_at => .autoconf_at,
                     .cmake => .cmake,
+                    .meson => .meson,
                     .blank => .blank,
                     .nasm => .nasm,
                 };
diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig
index 9d036dcf2db7b1417c60af507461d8ec647aeb9e..9aeebf1a1096fae7bfb4589e386c953839824f9a 100644
--- a/lib/std/Build/Step/ConfigHeader.zig
+++ b/lib/std/Build/Step/ConfigHeader.zig
@@ -27,6 +27,9 @@ pub const Style = union(enum) {
     /// The configure format supported by CMake. It uses `@FOO@`, `${}` and
     /// `#cmakedefine` for template substitution.
     cmake: std.Build.LazyPath,
+    /// The configure format supported by Meson. It uses `@FOO@`, and
+    /// `#mesondefine` for template substitution.
+    meson: std.Build.LazyPath,
     /// Instead of starting with an input file, start with nothing.
     blank,
     /// Start with nothing, like blank, and output a nasm .asm file.
@@ -34,7 +37,7 @@ pub const Style = union(enum) {
 
     pub fn getPath(style: Style) ?std.Build.LazyPath {
         switch (style) {
-            .autoconf_undef, .autoconf_at, .cmake => |s| return s,
+            .autoconf_undef, .autoconf_at, .cmake, .meson => |s| return s,
             .blank, .nasm => return null,
         }
     }
diff --git a/test/standalone/config_header/build.zig b/test/standalone/config_header/build.zig
index 88078ca2fae1eea50cffda5dff641d1566771e08..120c65c8532459a9cfcb3702c2d9b33492090e3f 100644
--- a/test/standalone/config_header/build.zig
+++ b/test/standalone/config_header/build.zig
@@ -51,6 +51,27 @@ pub fn build(b: *std.Build) void {
     });
     test_step.dependOn(&check_config_header_autoconf_at.step);
 
+    const config_header_meson = b.addConfigHeader(
+        .{ .style = .{
+            .meson = b.path("meson/mesondefine.h.in"),
+        } },
+        .{
+            .version = "1.2.3",
+            .boolean_true = true,
+            .boolean_false = false,
+            .uint_64 = 42,
+            .int_64 = -42,
+            .string = "meson",
+            .ident = .meson,
+            .not_defined = null,
+            .is_defined = {},
+        },
+    );
+    const check_config_header_meson = b.addCheckFile(config_header_meson.getOutputFile(), .{
+        .expected_exact = @embedFile("meson/mesondefine.h"),
+    });
+    test_step.dependOn(&check_config_header_meson.step);
+
     const config_header_blank = b.addConfigHeader(
         .{
             .style = .blank,
diff --git a/test/standalone/config_header/meson/mesondefine.h b/test/standalone/config_header/meson/mesondefine.h
new file mode 100644
index 0000000000000000000000000000000000000000..f70ffe0ef1c08bfb04071699300d4404b7905f62
--- /dev/null
+++ b/test/standalone/config_header/meson/mesondefine.h
@@ -0,0 +1,22 @@
+/* This file was generated by ConfigHeader using the Zig Build System. */
+// comments are preserved
+
+// empty lines are preserved
+
+#define VERSION_STR "1.2.3"
+
+#define boolean_true /* comment after define is okay */
+
+#undef boolean_false // same for line comment
+
+#define uint_64 42
+
+#define int_64 -42
+
+#define string "meson"
+
+#define ident meson
+
+/* #undef not_defined */
+
+#define is_defined
diff --git a/test/standalone/config_header/meson/mesondefine.h.in b/test/standalone/config_header/meson/mesondefine.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..b90f3054c29c4476da7d44f05afd20e69adc4acf
--- /dev/null
+++ b/test/standalone/config_header/meson/mesondefine.h.in
@@ -0,0 +1,21 @@
+// comments are preserved
+
+// empty lines are preserved
+
+#define VERSION_STR "@version@"
+
+#mesondefine boolean_true /* comment after define is okay */
+
+#mesondefine boolean_false // same for line comment
+
+#mesondefine uint_64
+
+#mesondefine int_64
+
+#mesondefine string
+
+#mesondefine ident
+
+#mesondefine not_defined
+
+#mesondefine is_defined
-- 
2.54.0


From 086f8d7b225df5ea15ef578411c94181fc53c464 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sun, 2 Aug 2026 09:47:39 +0200
Subject: [PATCH 105/215] update_glibc: exclude some 2.32 crt0 files

---
 tools/update_glibc.zig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig
index 29df298bf6c49d5e5f140069d5b607550ecca979..46242d8e8cad829c216b5ff3956f129c1c000e0c 100644
--- a/tools/update_glibc.zig
+++ b/tools/update_glibc.zig
@@ -36,6 +36,7 @@ const exempt_extensions = [_][]const u8{
     // These are the start files we use when targeting glibc <= 2.33.
     "-2.33.S",
     "-2.33.c",
+    "-2.32.c",
 };
 
 pub fn main(init: std.process.Init) !void {
-- 
2.54.0


From 846aa04a07161e865d0b28f653e1ff0a99b25840 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sun, 2 Aug 2026 09:47:16 +0200
Subject: [PATCH 106/215] libc: update NetBSD headers to 11.0-RELEASE

---
 lib/libc/include/generic-netbsd/fcntl.h       |  5 +-
 .../include/generic-netbsd/i386/mcontext.h    | 24 +++++-
 .../generic-netbsd/i386/wchar_limits.h        |  2 +-
 lib/libc/include/generic-netbsd/machine/pte.h | 51 ++++++++-----
 .../include/generic-netbsd/machine/vmparam.h  | 30 +++++---
 lib/libc/include/generic-netbsd/mips/pte.h    | 16 +++-
 .../generic-netbsd/netinet/tcp_timer.h        |  4 +-
 lib/libc/include/generic-netbsd/nfs/nfs.h     |  4 +-
 .../include/generic-netbsd/nfs/nfsmount.h     |  6 +-
 lib/libc/include/generic-netbsd/pthread.h     |  2 +-
 lib/libc/include/generic-netbsd/riscv/pte.h   | 51 ++++++++-----
 .../include/generic-netbsd/riscv/vmparam.h    | 30 +++++---
 lib/libc/include/generic-netbsd/sys/fcntl.h   |  5 +-
 lib/libc/include/generic-netbsd/sys/lua.h     |  4 +-
 lib/libc/include/generic-netbsd/sys/param.h   |  4 +-
 .../generic-netbsd/x86/cpu_extended_state.h   |  4 +-
 lib/libc/include/generic-netbsd/x86/fpu.h     |  8 +-
 .../include/generic-netbsd/x86/specialreg.h   | 76 +++++++++++++++++--
 .../powerpc-netbsd-eabi/powerpc/oea/pmap.h    | 10 ++-
 .../x86-netbsd-none/machine/mcontext.h        | 24 +++++-
 .../x86_64-netbsd-none/amd64/mcontext.h       | 33 +++++++-
 .../x86_64-netbsd-none/machine/mcontext.h     | 33 +++++++-
 22 files changed, 339 insertions(+), 87 deletions(-)

diff --git a/lib/libc/include/generic-netbsd/fcntl.h b/lib/libc/include/generic-netbsd/fcntl.h
index af43c74a3daca814d873e6bda87f497dc6f0de4b..311effadd406e25dae75c281ff217008e87ab001 100644
--- a/lib/libc/include/generic-netbsd/fcntl.h
+++ b/lib/libc/include/generic-netbsd/fcntl.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: fcntl.h,v 1.57 2025/07/25 23:24:46 kre Exp $	*/
+/*	$NetBSD: fcntl.h,v 1.57.2.1 2026/06/16 09:06:50 martin Exp $	*/
 
 /*-
  * Copyright (c) 1983, 1990, 1993
@@ -121,6 +121,9 @@
 #if defined(_NETBSD_SOURCE)
 #define	O_NOSIGPIPE	0x01000000	/* don't deliver sigpipe */
 #define	O_REGULAR	0x02000000	/* fail if not a regular file */
+#endif
+#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0 >= 700) || \
+    defined(_NETBSD_SOURCE)
 #define	O_EXEC		0x04000000	/* open for executing only */
 #endif
 #if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \
diff --git a/lib/libc/include/generic-netbsd/i386/mcontext.h b/lib/libc/include/generic-netbsd/i386/mcontext.h
index eca7a40be452d1894f78d3de2424c400ea2dbd6e..bf34279f20a8dfa0fb8aa61839b7de8b2b96f640 100644
--- a/lib/libc/include/generic-netbsd/i386/mcontext.h
+++ b/lib/libc/include/generic-netbsd/i386/mcontext.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.19 2024/11/30 01:04:10 christos Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -40,6 +40,7 @@
 #define	_UC_CLRSTACK	_UC_MD_BIT17
 #define	_UC_VM		_UC_MD_BIT18
 #define	_UC_TLSBASE	_UC_MD_BIT19
+#define	_UC_XSAVE	_UC_MD_BIT20
 
 /*
  * Layout of mcontext_t according to the System V Application Binary Interface,
@@ -85,6 +86,27 @@ typedef struct {
 			char	__fp_xmm[512];
 		} __fp_xmm_state;	/* x87 and xmm regs in fxsave format */
 		int	__fp_fpregs[128];
+		struct {
+			/*
+			 * `The XSAVE feature set does not use bytes
+			 *  511:416; bytes 463:416 are reserved.'
+			 *
+			 * We take a part out of this to form a pointer
+			 * to an external XSAVE area.  This way, we can
+			 * replicate the FXSAVE parts for the benefit
+			 * of userland programs that aren't aware of
+			 * the XSAVE pointer, have used the extended
+			 * CPU registers (ymmN/zmmN/&c.), and want to
+			 * examine the x87/SSE register state in a
+			 * signal handler.  The kernel does not use
+			 * this part.
+			 */
+			char		__fxsave[416];
+			char		__rsvd[48];
+			__greg_t	__xsaveptr;
+			__greg_t	__xsavelen;
+			char		__pad[40];
+		} __xsave;
 	} __fp_reg_set;
 	int 	__fp_pad[33];			/* Historic padding */
 } __fpregset_t;
diff --git a/lib/libc/include/generic-netbsd/i386/wchar_limits.h b/lib/libc/include/generic-netbsd/i386/wchar_limits.h
index e3bf3b7090c9ee41148b6edc36944d5dad30fe8e..76ee442d874d23f7e4570df9abf167a81d39b79b 100644
--- a/lib/libc/include/generic-netbsd/i386/wchar_limits.h
+++ b/lib/libc/include/generic-netbsd/i386/wchar_limits.h
@@ -44,4 +44,4 @@
 #define	WINT_MIN	(-0x7fffffff-1)			/* wint_t	  */
 #define	WINT_MAX	0x7fffffff			/* wint_t	  */
 
-#endif /* !_I386_WCHAR_LIMITS_H_ */
+#endif /* !_I386_WCHAR_LIMITS_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/generic-netbsd/machine/pte.h b/lib/libc/include/generic-netbsd/machine/pte.h
index 760dc280552255428ff7144e68346bb813c363cd..f19d4ffe10144f61bc3ef3a8fd35d06a81de4c78 100644
--- a/lib/libc/include/generic-netbsd/machine/pte.h
+++ b/lib/libc/include/generic-netbsd/machine/pte.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */
+/* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */
 
 /*
  * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
 	return (pte & PTE_D) != 0;
 }
 
+static inline bool
+pte_referenced_p(pt_entry_t pte)
+{
+	return (pte & PTE_A) != 0;
+}
+
 static inline bool
 pte_cached_p(pt_entry_t pte)
 {
@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
 }
 
 static inline pt_entry_t
-pte_prot_nowrite(pt_entry_t pte)
+pte_clear_modify(pt_entry_t pte)
 {
-	return pte & ~PTE_W;
+	return pte & ~PTE_D;
+}
+
+static inline pt_entry_t
+pte_clear_reference(pt_entry_t pte)
+{
+	return pte & ~PTE_A;
 }
 
 static inline pt_entry_t
@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
 	pte |= pte_prot_bits(mdpg, prot, kernel_p);
 	pte |= pte_enter_flags_to_pbmt(flags);
 
+	/*
+	 * pmap_enter should have checked flags and updated
+	 * VM_PAGEMD_{REFERENCED,MODIFIED}_P, so there is no
+	 * need here.
+	 */
+	KASSERT(((flags & VM_PROT_ALL) == 0) || VM_PAGEMD_REFERENCED_P(mdpg));
+	KASSERT(((flags & VM_PROT_WRITE) == 0) || VM_PAGEMD_MODIFIED_P(mdpg));
+
 	if (mdpg != NULL) {
-
-		if ((prot & VM_PROT_WRITE) != 0 &&
-		    ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {
+		if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
 			/*
-			* This is a writable mapping, and the page's mod state
-			* indicates it has already been modified.  No need for
-			* modified emulation.
-			*/
+			 * This is a writable mapping, and the page's mod state
+			 * indicates it has already been modified.  No need for
+			 * reference or modified emulation.
+			 */
 			pte |= PTE_A | PTE_D;
-		} else if ((flags & VM_PROT_ALL) || VM_PAGEMD_REFERENCED_P(mdpg)) {
+		} else if (VM_PAGEMD_REFERENCED_P(mdpg)) {
 			/*
-			* - The access type indicates that we don't need to do
-			*   referenced emulation.
-			* OR
-			* - The physical page has already been referenced so no need
-			*   to re-do referenced emulation here.
-			*/
+			 * The physical page has already been referenced so no need
+			 * to re-do referenced emulation here.
+			 */
 			pte |= PTE_A;
 		}
-	} else {
-		pte |= PTE_A | PTE_D;
 	}
 
 	return pte;
diff --git a/lib/libc/include/generic-netbsd/machine/vmparam.h b/lib/libc/include/generic-netbsd/machine/vmparam.h
index b483e18e8574ce42273a16ae6e90df2b10157c6c..ba9c754dce496cd5d52b0bda02691afeba05e979 100644
--- a/lib/libc/include/generic-netbsd/machine/vmparam.h
+++ b/lib/libc/include/generic-netbsd/machine/vmparam.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $	*/
 
 /*-
  * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
@@ -50,6 +50,25 @@
 #define	PAGE_SIZE	(1 << PAGE_SHIFT)
 #define	PAGE_MASK	(PAGE_SIZE - 1)
 
+#ifdef _LP64
+/*
+ * Default pager_map of 16MB is awfully small.  There is plenty
+ * of VA so use it.
+ */
+#define	PAGER_MAP_DEFAULT_SIZE (512 * 1024 * 1024)
+
+/*
+ * Defaults for Unified Buffer Cache parameters.
+ */
+
+#ifndef UBC_WINSHIFT
+#define	UBC_WINSHIFT	16	/* 64kB */
+#endif
+#ifndef UBC_NWINS
+#define	UBC_NWINS	4096	/* 256MB */
+#endif
+#endif
+
 /*
  * USRSTACK is the top (end) of the user stack.
  *
@@ -125,12 +144,6 @@
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)0xffffffd000000000)
 
 #else		/* Sv32 */
-/*
- * kernel virtual space layout:
- *   0x8000_0000  -   64GiB  KERNEL VM Space (inc. text/data/bss)
- *  (0x4000_0000      +1GiB) KERNEL VM start of KVA
- *  (0x0000_0000      64GiB) reserved
- */
 
 /*
  * kernel virtual space layout without direct map (common case)
@@ -154,13 +167,12 @@
  *
  */
 
-
-
 #define VM_MAXUSER_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
 #define VM_MIN_KERNEL_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)-0x10000000)	/* 0xffff_ffff_f000_0000 */
 
 #endif
+
 #define VM_KERNEL_BASE		VM_MIN_KERNEL_ADDRESS
 #define VM_KERNEL_SIZE		0x2000000	/* 32 MiB (8 / 16 megapages) */
 #define VM_KERNEL_DTB_BASE	(VM_KERNEL_BASE + VM_KERNEL_SIZE)
diff --git a/lib/libc/include/generic-netbsd/mips/pte.h b/lib/libc/include/generic-netbsd/mips/pte.h
index 986baa4788a4a805c38fb9abf7a22b1be167ecd5..4b41ce44e84d89be8bbd496407183ae801fdbe8c 100644
--- a/lib/libc/include/generic-netbsd/mips/pte.h
+++ b/lib/libc/include/generic-netbsd/mips/pte.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: pte.h,v 1.27 2020/08/22 15:34:51 skrll Exp $	*/
+/*	$NetBSD: pte.h,v 1.27.28.1 2026/06/03 18:17:03 martin Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -269,6 +269,12 @@ pte_modified_p(pt_entry_t pte)
 	return (pte & MIPS_MMU(PG_D)) != 0;
 }
 
+static inline bool
+pte_referenced_p(pt_entry_t pte)
+{
+	return false;
+}
+
 static inline bool
 pte_global_p(pt_entry_t pte)
 {
@@ -340,11 +346,17 @@ pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
 }
 
 static inline pt_entry_t
-pte_prot_nowrite(pt_entry_t pte)
+pte_clear_modify(pt_entry_t pte)
 {
 	return pte & ~MIPS_MMU(PG_D);
 }
 
+static inline pt_entry_t
+pte_clear_reference(pt_entry_t pte)
+{
+	return pte;
+}
+
 static inline pt_entry_t
 pte_cached_change(pt_entry_t pte, bool cached)
 {
diff --git a/lib/libc/include/generic-netbsd/netinet/tcp_timer.h b/lib/libc/include/generic-netbsd/netinet/tcp_timer.h
index 0cef4010264fec7628c35943f450a5671cc554d3..b27152185d19fbc7ff1a3bcf9e299827b9e00871 100644
--- a/lib/libc/include/generic-netbsd/netinet/tcp_timer.h
+++ b/lib/libc/include/generic-netbsd/netinet/tcp_timer.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: tcp_timer.h,v 1.30 2019/08/06 15:48:18 riastradh Exp $	*/
+/*	$NetBSD: tcp_timer.h,v 1.30.34.1 2026/07/19 15:51:03 martin Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2005 The NetBSD Foundation, Inc.
@@ -119,7 +119,7 @@
 #define	TCPTV_MSL	( 30*PR_SLOWHZ)		/* max seg lifetime (hah!) */
 #define	TCPTV_SRTTBASE	0			/* base roundtrip time;
 						   if 0, no idea yet */
-#define	TCPTV_SRTTDFLT	(  3*PR_SLOWHZ)		/* assumed RTT if no info */
+#define	TCPTV_SRTTDFLT	(  1*PR_SLOWHZ)		/* initial RTO; RFC 6298 (2.1) */
 
 #define	TCPTV_PERSMIN	(  5*PR_SLOWHZ)		/* retransmit persistance */
 #define	TCPTV_PERSMAX	( 60*PR_SLOWHZ)		/* maximum persist interval */
diff --git a/lib/libc/include/generic-netbsd/nfs/nfs.h b/lib/libc/include/generic-netbsd/nfs/nfs.h
index 8759c291d4faa0fd0e63eb9967fc8c2429ece6a9..cb66894f3100cb4d2f5c27e5182ffce64249e2fa 100644
--- a/lib/libc/include/generic-netbsd/nfs/nfs.h
+++ b/lib/libc/include/generic-netbsd/nfs/nfs.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs.h,v 1.81 2024/12/07 02:05:55 riastradh Exp $	*/
+/*	$NetBSD: nfs.h,v 1.81.2.1 2026/06/27 09:46:05 martin Exp $	*/
 /*
  * Copyright (c) 1989, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
@@ -451,6 +451,8 @@ struct nfssvc_sock {
 	int		ns_sflags;		/* b: */
 	int		ns_cc;			/* b: */
 	int		ns_reclen;		/* b: */
+	int		ns_frag_count;		/* b: */
+	int		ns_streamlen;		/* b: */
 	int		ns_numuids;
 	u_int32_t	ns_sref;		/* g: */
 	SIMPLEQ_HEAD(, nfsrv_descript) ns_sendq; /* s: send reply list */
diff --git a/lib/libc/include/generic-netbsd/nfs/nfsmount.h b/lib/libc/include/generic-netbsd/nfs/nfsmount.h
index 2a38bbd2cc5d098a77903043f413a503c9201453..8c418f4509b62647c63be23a70ec5e7272aeb684 100644
--- a/lib/libc/include/generic-netbsd/nfs/nfsmount.h
+++ b/lib/libc/include/generic-netbsd/nfs/nfsmount.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfsmount.h,v 1.54 2024/12/07 02:05:55 riastradh Exp $	*/
+/*	$NetBSD: nfsmount.h,v 1.54.2.1 2026/06/03 18:46:36 martin Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -92,13 +92,15 @@ struct nfs_args {
 #define	NFSMNT_READDIRSIZE	0x00020000  /* Set readdir size */
 #define NFSMNT_XLATECOOKIE	0x00040000  /* 32<->64 dir cookie xlation */
 #define	NFSMNT_NOAC		0x00080000  /* Turn off attribute cache */
+#define	NFSMNT_NOWCCMSG		0x00100000  /* Turn off attribute wcc messages */
 
 #define NFSMNT_BITS	"\177\20" \
     "b\00soft\0b\01wsize\0b\02rsize\0b\03timeo\0" \
     "b\04retrans\0b\05maxgrps\0b\06intr\0b\07noconn\0" \
     "b\10nqnfs\0b\11nfsv3\0b\12kerb\0b\13dumbtimr\0" \
     "b\14leaseterm\0b\15readahead\0b\16deadthresh\0b\17resvport\0" \
-    "b\20rdirplus\0b\21readdirsize\0b\22xlatecookie\0b\23noac\0"
+    "b\20rdirplus\0b\21readdirsize\0b\22xlatecookie\0b\23noac\0" \
+    "b\24nowccmsg\0"
 
 /*
  * NFS internal flags (nm_iflag) */
diff --git a/lib/libc/include/generic-netbsd/pthread.h b/lib/libc/include/generic-netbsd/pthread.h
index b530af73b802a2ce1cab22be7c9e422d90d08a0d..0d201332f4cb7fb92b1d13f4af7ccb37728ae4ca 100644
--- a/lib/libc/include/generic-netbsd/pthread.h
+++ b/lib/libc/include/generic-netbsd/pthread.h
@@ -461,4 +461,4 @@ __END_DECLS
 
 #endif /* __LIBPTHREAD_SOURCE__ */
 
-#endif /* _LIB_PTHREAD_H */
+#endif /* _LIB_PTHREAD_H */
\ No newline at end of file
diff --git a/lib/libc/include/generic-netbsd/riscv/pte.h b/lib/libc/include/generic-netbsd/riscv/pte.h
index 760dc280552255428ff7144e68346bb813c363cd..f19d4ffe10144f61bc3ef3a8fd35d06a81de4c78 100644
--- a/lib/libc/include/generic-netbsd/riscv/pte.h
+++ b/lib/libc/include/generic-netbsd/riscv/pte.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */
+/* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */
 
 /*
  * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
@@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte)
 	return (pte & PTE_D) != 0;
 }
 
+static inline bool
+pte_referenced_p(pt_entry_t pte)
+{
+	return (pte & PTE_A) != 0;
+}
+
 static inline bool
 pte_cached_p(pt_entry_t pte)
 {
@@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p)
 }
 
 static inline pt_entry_t
-pte_prot_nowrite(pt_entry_t pte)
+pte_clear_modify(pt_entry_t pte)
 {
-	return pte & ~PTE_W;
+	return pte & ~PTE_D;
+}
+
+static inline pt_entry_t
+pte_clear_reference(pt_entry_t pte)
+{
+	return pte & ~PTE_A;
 }
 
 static inline pt_entry_t
@@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
 	pte |= pte_prot_bits(mdpg, prot, kernel_p);
 	pte |= pte_enter_flags_to_pbmt(flags);
 
+	/*
+	 * pmap_enter should have checked flags and updated
+	 * VM_PAGEMD_{REFERENCED,MODIFIED}_P, so there is no
+	 * need here.
+	 */
+	KASSERT(((flags & VM_PROT_ALL) == 0) || VM_PAGEMD_REFERENCED_P(mdpg));
+	KASSERT(((flags & VM_PROT_WRITE) == 0) || VM_PAGEMD_MODIFIED_P(mdpg));
+
 	if (mdpg != NULL) {
-
-		if ((prot & VM_PROT_WRITE) != 0 &&
-		    ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {
+		if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) {
 			/*
-			* This is a writable mapping, and the page's mod state
-			* indicates it has already been modified.  No need for
-			* modified emulation.
-			*/
+			 * This is a writable mapping, and the page's mod state
+			 * indicates it has already been modified.  No need for
+			 * reference or modified emulation.
+			 */
 			pte |= PTE_A | PTE_D;
-		} else if ((flags & VM_PROT_ALL) || VM_PAGEMD_REFERENCED_P(mdpg)) {
+		} else if (VM_PAGEMD_REFERENCED_P(mdpg)) {
 			/*
-			* - The access type indicates that we don't need to do
-			*   referenced emulation.
-			* OR
-			* - The physical page has already been referenced so no need
-			*   to re-do referenced emulation here.
-			*/
+			 * The physical page has already been referenced so no need
+			 * to re-do referenced emulation here.
+			 */
 			pte |= PTE_A;
 		}
-	} else {
-		pte |= PTE_A | PTE_D;
 	}
 
 	return pte;
diff --git a/lib/libc/include/generic-netbsd/riscv/vmparam.h b/lib/libc/include/generic-netbsd/riscv/vmparam.h
index b483e18e8574ce42273a16ae6e90df2b10157c6c..ba9c754dce496cd5d52b0bda02691afeba05e979 100644
--- a/lib/libc/include/generic-netbsd/riscv/vmparam.h
+++ b/lib/libc/include/generic-netbsd/riscv/vmparam.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $	*/
 
 /*-
  * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc.
@@ -50,6 +50,25 @@
 #define	PAGE_SIZE	(1 << PAGE_SHIFT)
 #define	PAGE_MASK	(PAGE_SIZE - 1)
 
+#ifdef _LP64
+/*
+ * Default pager_map of 16MB is awfully small.  There is plenty
+ * of VA so use it.
+ */
+#define	PAGER_MAP_DEFAULT_SIZE (512 * 1024 * 1024)
+
+/*
+ * Defaults for Unified Buffer Cache parameters.
+ */
+
+#ifndef UBC_WINSHIFT
+#define	UBC_WINSHIFT	16	/* 64kB */
+#endif
+#ifndef UBC_NWINS
+#define	UBC_NWINS	4096	/* 256MB */
+#endif
+#endif
+
 /*
  * USRSTACK is the top (end) of the user stack.
  *
@@ -125,12 +144,6 @@
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)0xffffffd000000000)
 
 #else		/* Sv32 */
-/*
- * kernel virtual space layout:
- *   0x8000_0000  -   64GiB  KERNEL VM Space (inc. text/data/bss)
- *  (0x4000_0000      +1GiB) KERNEL VM start of KVA
- *  (0x0000_0000      64GiB) reserved
- */
 
 /*
  * kernel virtual space layout without direct map (common case)
@@ -154,13 +167,12 @@
  *
  */
 
-
-
 #define VM_MAXUSER_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
 #define VM_MIN_KERNEL_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)-0x10000000)	/* 0xffff_ffff_f000_0000 */
 
 #endif
+
 #define VM_KERNEL_BASE		VM_MIN_KERNEL_ADDRESS
 #define VM_KERNEL_SIZE		0x2000000	/* 32 MiB (8 / 16 megapages) */
 #define VM_KERNEL_DTB_BASE	(VM_KERNEL_BASE + VM_KERNEL_SIZE)
diff --git a/lib/libc/include/generic-netbsd/sys/fcntl.h b/lib/libc/include/generic-netbsd/sys/fcntl.h
index af43c74a3daca814d873e6bda87f497dc6f0de4b..311effadd406e25dae75c281ff217008e87ab001 100644
--- a/lib/libc/include/generic-netbsd/sys/fcntl.h
+++ b/lib/libc/include/generic-netbsd/sys/fcntl.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: fcntl.h,v 1.57 2025/07/25 23:24:46 kre Exp $	*/
+/*	$NetBSD: fcntl.h,v 1.57.2.1 2026/06/16 09:06:50 martin Exp $	*/
 
 /*-
  * Copyright (c) 1983, 1990, 1993
@@ -121,6 +121,9 @@
 #if defined(_NETBSD_SOURCE)
 #define	O_NOSIGPIPE	0x01000000	/* don't deliver sigpipe */
 #define	O_REGULAR	0x02000000	/* fail if not a regular file */
+#endif
+#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0 >= 700) || \
+    defined(_NETBSD_SOURCE)
 #define	O_EXEC		0x04000000	/* open for executing only */
 #endif
 #if (_POSIX_C_SOURCE - 0) >= 202405L || (_XOPEN_SOURCE - 0 >= 800) || \
diff --git a/lib/libc/include/generic-netbsd/sys/lua.h b/lib/libc/include/generic-netbsd/sys/lua.h
index 2657da9e21de60c9a06eb7fcc80afbe6441cc2d2..8c820f69cd81e6074d2b75cf825eb63b1ceca35c 100644
--- a/lib/libc/include/generic-netbsd/sys/lua.h
+++ b/lib/libc/include/generic-netbsd/sys/lua.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: lua.h,v 1.9 2023/07/11 14:57:21 martin Exp $ */
+/*	$NetBSD: lua.h,v 1.9.8.1 2026/06/29 19:52:23 martin Exp $ */
 
 /*
  * Copyright (c) 2014 by Lourival Vieira Neto .
@@ -33,7 +33,9 @@
 #define _SYS_LUA_H_
 
 #include 
+
 #include 
+#include 
 
 #include 		/* for lua_State */
 
diff --git a/lib/libc/include/generic-netbsd/sys/param.h b/lib/libc/include/generic-netbsd/sys/param.h
index 2590fadb10c70c69eb8735d851e4111e9206e7e3..423ccfd7ce7797dfeebb3008147363821784d01b 100644
--- a/lib/libc/include/generic-netbsd/sys/param.h
+++ b/lib/libc/include/generic-netbsd/sys/param.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.738.2.5 2026/05/12 04:23:51 martin Exp $	*/
+/*	$NetBSD: param.h,v 1.738.2.9 2026/07/30 15:23:12 martin Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -566,4 +566,4 @@ extern size_t coherency_unit;
 #endif
 #endif /* !__ASSEMBLER__ */
 
-#endif /* !_SYS_PARAM_H_ */
+#endif /* !_SYS_PARAM_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/generic-netbsd/x86/cpu_extended_state.h b/lib/libc/include/generic-netbsd/x86/cpu_extended_state.h
index ccad28305b4e3e4f49b5940ee1b98361e10887e8..d45664ead197649dcde26de0dbef00d29ffc8a55 100644
--- a/lib/libc/include/generic-netbsd/x86/cpu_extended_state.h
+++ b/lib/libc/include/generic-netbsd/x86/cpu_extended_state.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu_extended_state.h,v 1.19 2025/04/24 01:50:39 riastradh Exp $	*/
+/*	$NetBSD: cpu_extended_state.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $	*/
 
 #ifndef _X86_CPU_EXTENDED_STATE_H_
 #define _X86_CPU_EXTENDED_STATE_H_
@@ -142,6 +142,8 @@ struct xsave_header {
 };
 __CTASSERT(sizeof(struct xsave_header) == 512 + 64);
 
+#define	XSAVE_ALIGN	64
+
 /*
  * The ymm save area actually follows the xsave_header.
  */
diff --git a/lib/libc/include/generic-netbsd/x86/fpu.h b/lib/libc/include/generic-netbsd/x86/fpu.h
index 311cd9655549bab305e2c74063d7649da9649a93..e1280905a59724cfc05cb74005d9f3cb7d6a25d8 100644
--- a/lib/libc/include/generic-netbsd/x86/fpu.h
+++ b/lib/libc/include/generic-netbsd/x86/fpu.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.h,v 1.23 2020/10/24 07:14:29 mgorny Exp $	*/
+/*	$NetBSD: fpu.h,v 1.23.28.1 2026/07/19 15:57:27 martin Exp $	*/
 
 #ifndef	_X86_FPU_H_
 #define	_X86_FPU_H_
@@ -46,6 +46,12 @@ int process_read_xstate(struct lwp *, struct xstate *);
 int process_verify_xstate(const struct xstate *);
 int process_write_xstate(struct lwp *, const struct xstate *);
 
+bool process_xsave_needed_p(struct lwp *);
+void process_read_xsave(struct lwp *, const struct xsave_header **, size_t *);
+int process_verify_xsavelen(struct lwp *, size_t);
+int process_verify_xsave(struct lwp *, const struct xsave_header *, size_t);
+void process_write_xsave(struct lwp *, const struct xsave_header *, size_t);
+
 #endif
 
 #endif /* _X86_FPU_H_ */
\ No newline at end of file
diff --git a/lib/libc/include/generic-netbsd/x86/specialreg.h b/lib/libc/include/generic-netbsd/x86/specialreg.h
index 5158f8c4fab86eabf620d0c69394165e4d9d1707..36635ca349a1a9d3459471f003074119c1a94c0c 100644
--- a/lib/libc/include/generic-netbsd/x86/specialreg.h
+++ b/lib/libc/include/generic-netbsd/x86/specialreg.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: specialreg.h,v 1.219 2025/04/28 13:01:27 riastradh Exp $	*/
+/*	$NetBSD: specialreg.h,v 1.219.2.1 2026/07/19 15:57:27 martin Exp $	*/
 
 /*
  * Copyright (c) 2014-2020 The NetBSD Foundation, Inc.
@@ -183,16 +183,82 @@
 	"\0"
 
 /*
- * Known FPU bits, only these get enabled. The save area is sized for all the
- * fields below.
+ * XCR0_FPU: Known FPU bits, only these get enabled.  The save area is
+ * sized for all the fields below.
+ *
+ * Any bits added to this will expand the extended CPU state that we
+ * may have to save and restore with XSAVE for userland processes,
+ * either in the kernel when preempting threads, or on the user's stack
+ * when delivering a signal.
+ *
+ * The kernel can dyanmically allocate larger sizes (on amd64, anyway,
+ * though not currently on i386 or Xen PV).  But if the XSAVE area is
+ * expanded so much that it and mcontext_t exceed MINSIGSTKSZ
+ * (currently 8192), a userland ABI change and compatibility layer is
+ * required to accommodate that, because existing programs may use
+ * sigaltstack(2) with stacks sized for the old MINSIGSTKSZ.
+ *
+ * The current stack requirement is 3160 bytes of space plus up to
+ * 63+15+8=86 bytes of padding for alignment (could be reduced by
+ * around 512 bytes by having mcontext_t overlap with the XSAVE area a
+ * little in machdep.c cpu_getmcontext_xsave, but we don't do that
+ * right now):
+ *
+ * - mcontext_t (728 bytes: general registers and 512-byte FXSAVE area)
+ * - XSAVE header (576 bytes: 512 bytes of FXSAVE, 64 bytes of metadata)
+ * - AVX state: ymm0..ymm15 high 128-bit halves (256 bytes)
+ * - AVX-512 state:
+ *   . k0..k7 opmask registers (64 bytes)
+ *   . zmm0..zmm15 high 256-bit halves (512 bytes)
+ *   . zmm16..zmm31 registers (1024 bytes)
+ *
+ * Likely future extensions that would expand the state beyond
+ * MINSIGSTKSZ:
+ *
+ * - AMX (Advanced Matrix Extensions) and ACE (AI Compute Extensions)
+ *   state:
+ *   . [AMX/ACE] TILECFG (64 bytes)
+ *   . [AMX/ACE] TILEDATA (8192 bytes)
+ *   . [ACE] SCALEDATA (128 bytes)
+ *
+ * As a precaution against ABI breakage, x86/identcpu.c will panic at
+ * boot if the XSAVE state size enabled in XCR0 exceeds MINSIGSTKSZ.
+ *
+ * References:
+ *
+ * - Intel 64 and IA-32 Architectures Software Developer's Manual,
+ *   Volume 1: Basic Architecture, Intel, Order Number: 253665-092US,
+ *   June 2026, Sec. 13.1 `XSAVE-Supported Features and State-Component
+ *   Bitmaps', pp. 13-1 -- 13-2.
+ *   https://web.archive.org/web/20260709150417/https://cdrdv2-public.intel.com/922477/253665-092-sdm-vol-1.pdf
+ *
+ * - AI Compute Extensions (ACE) Specification, x86 Ecosystem Advisory
+ *   Group, Version 1.15, 2026-05-15, Sec 15.4.1 `XSAVE State
+ *   Components', p. 86.
+ *   https://web.archive.org/web/20260619062626/https://x86ecosystem.org/wp-content/uploads/2026/06/ACE_v1_Specification_public_1_15.pdf
  */
 #if defined __i386__ || defined XENPV /* XXX XENPV PR kern/59371 */
 #define XCR0_FPU	(XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
 			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
 #else
 #define XCR0_FPU	(XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
-			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM | \
-			 XCR0_TILECFG | XCR0_TILEDATA)
+			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
+#endif
+
+/*
+ * Maximum size of XSAVE state that we can handle without ABI changes
+ * to userland.  Must match usage in cpu_getmcontext.  Extra 8 is neeed
+ * on amd64 to have space for return address in 16-byte-aligned stack
+ * frame.
+ */
+#ifdef __x86_64__
+#define	XSAVE_MAX_BYTES							      \
+	(MINSIGSTKSZ - (8 + STACK_ALIGNBYTES +				      \
+	    sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1)))
+#else
+#define	XSAVE_MAX_BYTES							      \
+	(MINSIGSTKSZ - (STACK_ALIGNBYTES +				      \
+	    sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1)))
 #endif
 
 /*
diff --git a/lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h b/lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h
index 8510dfa5f6337ddab007b85ea157e17a4aa396c6..b0584b636d5db885176da01d834d116b31dc8574 100644
--- a/lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h
+++ b/lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.39 2023/12/15 09:42:33 rin Exp $	*/
+/*	$NetBSD: pmap.h,v 1.39.4.1 2026/07/03 17:51:59 martin Exp $	*/
 
 /*-
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -122,11 +122,13 @@ __BEGIN_DECLS
 #include 
 
 /*
- * For OEA and OEA64_BRIDGE, we guarantee that pa below USER_ADDR
- * (== 3GB < VM_MIN_KERNEL_ADDRESS) is direct-mapped.
+ * Physical memory below PMAP_DIRECT_MAPPED_LEN is direct-mapped 
+ * (pa == va). Direct region covers the segments below BOTH 
+ * the user copyin window (USER_SR) and the kernel HTAB window
+ * (KERNEL_SR), so it can never overlap.
  */
 #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE)
-#define	PMAP_DIRECT_MAPPED_SR	(USER_SR - 1)
+#define	PMAP_DIRECT_MAPPED_SR	(MIN(USER_SR, KERNEL_SR) - 1)
 #define	PMAP_DIRECT_MAPPED_LEN \
     ((vaddr_t)SEGMENT_LENGTH * (PMAP_DIRECT_MAPPED_SR + 1))
 #endif
diff --git a/lib/libc/include/x86-netbsd-none/machine/mcontext.h b/lib/libc/include/x86-netbsd-none/machine/mcontext.h
index eca7a40be452d1894f78d3de2424c400ea2dbd6e..bf34279f20a8dfa0fb8aa61839b7de8b2b96f640 100644
--- a/lib/libc/include/x86-netbsd-none/machine/mcontext.h
+++ b/lib/libc/include/x86-netbsd-none/machine/mcontext.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.19 2024/11/30 01:04:10 christos Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -40,6 +40,7 @@
 #define	_UC_CLRSTACK	_UC_MD_BIT17
 #define	_UC_VM		_UC_MD_BIT18
 #define	_UC_TLSBASE	_UC_MD_BIT19
+#define	_UC_XSAVE	_UC_MD_BIT20
 
 /*
  * Layout of mcontext_t according to the System V Application Binary Interface,
@@ -85,6 +86,27 @@ typedef struct {
 			char	__fp_xmm[512];
 		} __fp_xmm_state;	/* x87 and xmm regs in fxsave format */
 		int	__fp_fpregs[128];
+		struct {
+			/*
+			 * `The XSAVE feature set does not use bytes
+			 *  511:416; bytes 463:416 are reserved.'
+			 *
+			 * We take a part out of this to form a pointer
+			 * to an external XSAVE area.  This way, we can
+			 * replicate the FXSAVE parts for the benefit
+			 * of userland programs that aren't aware of
+			 * the XSAVE pointer, have used the extended
+			 * CPU registers (ymmN/zmmN/&c.), and want to
+			 * examine the x87/SSE register state in a
+			 * signal handler.  The kernel does not use
+			 * this part.
+			 */
+			char		__fxsave[416];
+			char		__rsvd[48];
+			__greg_t	__xsaveptr;
+			__greg_t	__xsavelen;
+			char		__pad[40];
+		} __xsave;
 	} __fp_reg_set;
 	int 	__fp_pad[33];			/* Historic padding */
 } __fpregset_t;
diff --git a/lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h b/lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h
index 9d70991fa91fe048ff0eba745c83912464a15682..911c0c7c0ce632d0643001b55fe627cc56908d38 100644
--- a/lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h
+++ b/lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -56,7 +56,28 @@ typedef	__greg_t	__gregset_t[_NGREG];
  * which requires 16 byte alignment. However the mcontext version
  * is never directly accessed.
  */
-typedef char __fpregset_t[512] __aligned(8);
+typedef union {
+	char	__fxsave[512] __aligned(8);
+	struct {
+		/*
+		 * `The XSAVE feature set does not use bytes 511:416;
+		 *  bytes 463:416 are reserved.'
+		 *
+		 * We take a part out of this to form a pointer to an
+		 * external XSAVE area.  This way, we can replicate the
+		 * FXSAVE parts for the benefit of userland programs
+		 * that aren't aware of the XSAVE pointer, have used
+		 * the extended CPU registers (ymmN/zmmN/&c.), and want
+		 * to examine the x87/SSE register state in a signal
+		 * handler.  The kernel does not use this part.
+		 */
+		char		__fxsave[416];
+		char		__rsvd[48];
+		__greg_t	__xsaveptr;
+		__greg_t	__xsavelen;
+		char		__pad[32];
+	}	__xsave;
+} __fpregset_t;
 
 typedef struct {
 	__gregset_t	__gregs;
@@ -75,6 +96,7 @@ typedef struct {
 #define	_UC_MACHINE_SET_PC(uc, pc)	_UC_MACHINE_PC(uc) = (pc)
 
 #define	_UC_TLSBASE	_UC_MD_BIT19
+#define	_UC_XSAVE	_UC_MD_BIT20
 
 /*
  * mcontext extensions to handle signal delivery.
@@ -127,6 +149,13 @@ typedef struct {
 		struct {
 			char	__fp_xmm[512];
 		} __fp_xmm_state;
+		struct {
+			char		__fxsave[416];
+			char		__rsvd[48];
+			__greg32_t	__xsaveptr;
+			__greg32_t	__xsavelen;
+			char		__pad[40];
+		} __xsave;
 	} __fp_reg_set;
 	int	__fp_pad[33];			/* Historic padding */
 } __fpregset32_t;
diff --git a/lib/libc/include/x86_64-netbsd-none/machine/mcontext.h b/lib/libc/include/x86_64-netbsd-none/machine/mcontext.h
index 9d70991fa91fe048ff0eba745c83912464a15682..911c0c7c0ce632d0643001b55fe627cc56908d38 100644
--- a/lib/libc/include/x86_64-netbsd-none/machine/mcontext.h
+++ b/lib/libc/include/x86_64-netbsd-none/machine/mcontext.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -56,7 +56,28 @@ typedef	__greg_t	__gregset_t[_NGREG];
  * which requires 16 byte alignment. However the mcontext version
  * is never directly accessed.
  */
-typedef char __fpregset_t[512] __aligned(8);
+typedef union {
+	char	__fxsave[512] __aligned(8);
+	struct {
+		/*
+		 * `The XSAVE feature set does not use bytes 511:416;
+		 *  bytes 463:416 are reserved.'
+		 *
+		 * We take a part out of this to form a pointer to an
+		 * external XSAVE area.  This way, we can replicate the
+		 * FXSAVE parts for the benefit of userland programs
+		 * that aren't aware of the XSAVE pointer, have used
+		 * the extended CPU registers (ymmN/zmmN/&c.), and want
+		 * to examine the x87/SSE register state in a signal
+		 * handler.  The kernel does not use this part.
+		 */
+		char		__fxsave[416];
+		char		__rsvd[48];
+		__greg_t	__xsaveptr;
+		__greg_t	__xsavelen;
+		char		__pad[32];
+	}	__xsave;
+} __fpregset_t;
 
 typedef struct {
 	__gregset_t	__gregs;
@@ -75,6 +96,7 @@ typedef struct {
 #define	_UC_MACHINE_SET_PC(uc, pc)	_UC_MACHINE_PC(uc) = (pc)
 
 #define	_UC_TLSBASE	_UC_MD_BIT19
+#define	_UC_XSAVE	_UC_MD_BIT20
 
 /*
  * mcontext extensions to handle signal delivery.
@@ -127,6 +149,13 @@ typedef struct {
 		struct {
 			char	__fp_xmm[512];
 		} __fp_xmm_state;
+		struct {
+			char		__fxsave[416];
+			char		__rsvd[48];
+			__greg32_t	__xsaveptr;
+			__greg32_t	__xsavelen;
+			char		__pad[40];
+		} __xsave;
 	} __fp_reg_set;
 	int	__fp_pad[33];			/* Historic padding */
 } __fpregset32_t;
-- 
2.54.0


From 833105128485bf84a22f26506eb5e7b9bfa146a0 Mon Sep 17 00:00:00 2001
From: Theo Fabi 
Date: Thu, 23 Jul 2026 11:54:00 -0400
Subject: [PATCH 107/215] debug.Dwarf: FORM_ref_addr is host address sized in
 DWARFv2

DW_FORM_ref_addr encoding specification is different in dwarf version 2.
parseFormValue() now accepts a `version` argument so that it can parse
such attributes correctly based on the version.
---
 lib/std/debug/Dwarf.zig | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig
index 75b6d71f2d488fdf24fd53c96bab1fa5d8bb4573..2d6e2204a340effe84ef4d2c00f1b87ea5cc1a5c 100644
--- a/lib/std/debug/Dwarf.zig
+++ b/lib/std/debug/Dwarf.zig
@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
                 unit_header.format,
                 endian,
                 address_size,
+                version,
             )) orelse continue;
 
             switch (die_obj.tag_id) {
@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
                                     unit_header.format,
                                     endian,
                                     address_size,
+                                    version,
                                 )) orelse return bad();
                             } else if (this_die_obj.getAttr(AT.specification)) |_| {
                                 const after_die_offset = fr.seek;
@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
                                     unit_header.format,
                                     endian,
                                     address_size,
+                                    version,
                                 )) orelse return bad();
                             } else {
                                 break :x null;
@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi
             unit_header.format,
             endian,
             address_size,
+            version,
         )) orelse return bad();
 
         if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
@@ -931,6 +935,7 @@ fn parseDie(
     format: Format,
     endian: Endian,
     addr_size_bytes: u8,
+    version: u16,
 ) ScanError!?Die {
     const abbrev_code = try fr.takeLeb128(u64);
     if (abbrev_code == 0) return null;
@@ -939,7 +944,7 @@ fn parseDie(
     const attrs = attrs_buf[0..table_entry.attrs.len];
     for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{
         .id = attr.id,
-        .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload),
+        .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload, version),
     };
     return .{
         .tag_id = table_entry.tag_id,
@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
             for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
                 e.* = .{ .path = &.{} };
                 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
-                    const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);
+                    const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
                     switch (ent_fmt.content_type_code) {
                         DW.LNCT.path => e.path = try form_value.getString(d.*),
                         DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
@@ -1074,7 +1079,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
         for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
             e.* = .{ .path = &.{} };
             for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
-                const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);
+                const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
                 switch (ent_fmt.content_type_code) {
                     DW.LNCT.path => e.path = try form_value.getString(d.*),
                     DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
@@ -1285,6 +1290,7 @@ fn parseFormValue(
     endian: Endian,
     addr_size_bytes: u8,
     implicit_const: ?i64,
+    version: u16,
 ) ScanError!FormValue {
     return switch (form_id) {
         // DWARF5.pdf page 213: the size of this value is encoded in the
@@ -1319,7 +1325,12 @@ fn parseFormValue(
         FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
         FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },
 
-        FORM.ref_addr => .{ .ref_addr = try readFormatSizedInt(r, format, endian) },
+        FORM.ref_addr => .{
+            .ref_addr = switch (version) {
+                2 => try readAddress(r, endian, addr_size_bytes),
+                else => try readFormatSizedInt(r, format, endian),
+            },
+        },
         FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
 
         FORM.string => .{ .string = try r.takeSentinel(0) },
@@ -1330,7 +1341,7 @@ fn parseFormValue(
         FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
         FORM.strx => .{ .strx = try r.takeLeb128(usize) },
         FORM.line_strp => .{ .line_strp = try readFormatSizedInt(r, format, endian) },
-        FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const),
+        FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const, version),
         FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
         FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
         FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },
-- 
2.54.0


From 12dc2f261166fe901ed955a1e87fcf292e3b1b86 Mon Sep 17 00:00:00 2001
From: Elaine Gibson 
Date: Sat, 1 Aug 2026 22:43:06 +0100
Subject: [PATCH 108/215] std: pass null for infinite NtWaitForSingleObject
 timeout

fixes #31954
---
 lib/std/Io/Threaded.zig               | 6 ++----
 lib/std/Thread.zig                    | 3 +--
 test/standalone/windows_argv/fuzz.zig | 3 +--
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index 457e4a255f857a80bd7f487b52c9db83027a4370..c6473678a20326c606cabf29bd16e27af9ffd843 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -15347,8 +15347,7 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT
     _ = windows.ntdll.RtlReportSilentProcessExit(handle, @fromBackingInt(@intCast(exit_code)));
     switch (windows.ntdll.NtTerminateProcess(handle, @fromBackingInt(@intCast(exit_code)))) {
         .SUCCESS, .PROCESS_IS_TERMINATING => {
-            const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
-            _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, &infinite_timeout);
+            _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, null);
             childCleanupWindows(child);
         },
         .ACCESS_DENIED => {
@@ -15371,8 +15370,7 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child
     const handle = child.id.?;
 
     const alertable_syscall: AlertableSyscall = try .start();
-    const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
-    while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, &infinite_timeout)) {
+    while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, null)) {
         windows.NTSTATUS.WAIT_0 => break alertable_syscall.finish(),
         .USER_APC, .ALERTED, .TIMEOUT => {
             try alertable_syscall.checkCancel();
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 05125adbe852a3586b4d77fa2d0f8f7dd4d4bb94..ad3fc383d9f5564d88ffec430d390f8cb75fd9bb 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -639,8 +639,7 @@ const WindowsThreadImpl = struct {
     }
 
     fn join(self: Impl) void {
-        const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
-        switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, &infinite_timeout)) {
+        switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, null)) {
             windows.NTSTATUS.WAIT_0 => {},
             else => |status| windows.unexpectedStatus(status) catch unreachable,
         }
diff --git a/test/standalone/windows_argv/fuzz.zig b/test/standalone/windows_argv/fuzz.zig
index 5169a3f54e42688eeb16532657f012cdb9edb422..743f73f7c96712d0823448f36fe69f31d518df71 100644
--- a/test/standalone/windows_argv/fuzz.zig
+++ b/test/standalone/windows_argv/fuzz.zig
@@ -147,8 +147,7 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO
         break :spawn proc_info.hProcess;
     };
     defer windows.CloseHandle(child_proc);
-    const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER);
-    switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, &infinite_timeout)) {
+    switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, null)) {
         windows.NTSTATUS.WAIT_0 => {},
         .TIMEOUT => return error.WaitTimeOut,
         else => |status| return windows.unexpectedStatus(status),
-- 
2.54.0


From 407061498ce1d23ec498cce234433d18668d46be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9E=97=E6=99=A8=20=28Leo=20Cheng=29?=
 
Date: Fri, 10 Jul 2026 13:15:20 +0800
Subject: [PATCH 109/215] std.Io: fix missing word in
 Clock.cpu_process/cpu_thread doc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: 林晨 (Leo Cheng) 
---
 lib/std/Io.zig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index a680c9d198583eac1b1969d6e92c8ae1065886c3..906ba85f72d1014b9b17341c25e16cc775943b3a 100644
--- a/lib/std/Io.zig
+++ b/lib/std/Io.zig
@@ -778,10 +778,10 @@ pub const Clock = enum {
     /// * On Linux, corresponds `CLOCK_BOOTTIME`.
     /// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`.
     boot,
-    /// Tracks the amount of CPU in user or kernel mode used by the calling
+    /// Tracks the amount of CPU time in user or kernel mode used by the calling
     /// process.
     cpu_process,
-    /// Tracks the amount of CPU in user or kernel mode used by the calling
+    /// Tracks the amount of CPU time in user or kernel mode used by the calling
     /// thread.
     cpu_thread,
 
-- 
2.54.0


From 9bc98f5911dd30ce4f0b62c6cc5eaaeb6d6b5e2d Mon Sep 17 00:00:00 2001
From: Meghan Denny 
Date: Tue, 19 May 2026 18:27:58 -0700
Subject: [PATCH 110/215] sema: improve ignored error value compile error
 message

---
 src/Sema.zig                                              | 6 ++++--
 .../compile_errors/ignored_deferred_function_call.zig     | 4 ++--
 .../ignored_expression_in_while_continuation.zig          | 8 ++++----
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig
index 09268824c6dd2063f6a94d836416a36375c11e42..ba5ad7eb1566c69ee5377a8269d3ac512e073d31 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -3182,10 +3182,12 @@ fn ensureResultUsed(
     const zcu = pt.zcu;
     switch (ty.zigTypeTag(zcu)) {
         .void, .noreturn => return,
-        .error_set => return sema.fail(block, src, "error set is ignored", .{}),
+        .error_set => {
+            return sema.fail(block, src, "error set of type '{f}' is ignored", .{ty.fmt(pt)});
+        },
         .error_union => {
             const msg = msg: {
-                const msg = try sema.errMsg(src, "error union is ignored", .{});
+                const msg = try sema.errMsg(src, "error union of type '{f}' is ignored", .{ty.fmt(pt)});
                 errdefer msg.destroy(sema.gpa);
                 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
                 break :msg msg;
diff --git a/test/cases/compile_errors/ignored_deferred_function_call.zig b/test/cases/compile_errors/ignored_deferred_function_call.zig
index 9980128f90de825fe1dc542d35357cea925db948..63a7f489f1b01fedbfdf6354a6a87671ddd7bb20 100644
--- a/test/cases/compile_errors/ignored_deferred_function_call.zig
+++ b/test/cases/compile_errors/ignored_deferred_function_call.zig
@@ -14,6 +14,6 @@ fn bar2() anyerror {
 
 // error
 //
-// :2:14: error: error union is ignored
+// :2:14: error: error union of type 'anyerror!i32' is ignored
 // :2:14: note: consider using 'try', 'catch', or 'if'
-// :9:15: error: error set is ignored
+// :9:15: error: error set of type 'anyerror' is ignored
diff --git a/test/cases/compile_errors/ignored_expression_in_while_continuation.zig b/test/cases/compile_errors/ignored_expression_in_while_continuation.zig
index 4d4441fa9bc9309e03ce43fbb5ac52a90a478f62..79553e16049c44e30f11a1eb587120843693e79a 100644
--- a/test/cases/compile_errors/ignored_expression_in_while_continuation.zig
+++ b/test/cases/compile_errors/ignored_expression_in_while_continuation.zig
@@ -24,10 +24,10 @@ fn bad2() anyerror {
 
 // error
 //
-// :2:24: error: error union is ignored
+// :2:24: error: error union of type 'anyerror!void' is ignored
 // :2:24: note: consider using 'try', 'catch', or 'if'
-// :7:25: error: error union is ignored
+// :7:25: error: error union of type 'anyerror!void' is ignored
 // :7:25: note: consider using 'try', 'catch', or 'if'
-// :12:25: error: error union is ignored
+// :12:25: error: error union of type 'anyerror!void' is ignored
 // :12:25: note: consider using 'try', 'catch', or 'if'
-// :19:25: error: error set is ignored
+// :19:25: error: error set of type 'anyerror' is ignored
-- 
2.54.0


From 95396e2c5d14fed2070742c0da41ecfbcd012978 Mon Sep 17 00:00:00 2001
From: David 
Date: Sun, 2 Aug 2026 12:25:11 +0200
Subject: [PATCH 111/215] std.c: update EV, EVFILT, NOTE enums for FreeBSD and
 macOS (#36206)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: David Czihak 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36206
Reviewed-by: Alex Rønne Petersen 
---
 lib/std/c.zig | 48 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/lib/std/c.zig b/lib/std/c.zig
index c6a3739972ca0f4b105d9f8168f7e329f15ff184..9f0feda6b37e4146bcebbdf26bdb97aefb4e7508 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -9736,6 +9736,7 @@ pub const SS = switch (native_os) {
 
 pub const EV = switch (native_os) {
     .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
+        // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
         /// add event to kq (implies enable)
         pub const ADD = 0x0001;
         /// delete event from kq
@@ -9771,11 +9772,14 @@ pub const EV = switch (native_os) {
         pub const FLAG0 = 0x1000;
         /// filter-specific flag
         pub const FLAG1 = 0x2000;
-        /// EOF detected
+        /// EOF detected (return value)
         pub const EOF = 0x8000;
-        /// error, data contains errno
+        /// error, data contains errno (return value)
         pub const ERROR = 0x4000;
+        /// use poll(2) semantics for EVFILT.READ
         pub const POLL = FLAG0;
+        /// on input, filter should actively return in the presence of OOB on the descriptor
+        /// on output, indicates the presence of OOB data on the descriptor
         pub const OOBAND = FLAG1;
     },
     .dragonfly => struct {
@@ -9818,6 +9822,7 @@ pub const EV = switch (native_os) {
         pub const EOF = 0x8000;
     },
     .freebsd => struct {
+        // https://cgit.freebsd.org/src/tree/sys/sys/event.h
         /// add event to kq (implies enable)
         pub const ADD = 0x0001;
         /// delete event from kq
@@ -9826,12 +9831,14 @@ pub const EV = switch (native_os) {
         pub const ENABLE = 0x0004;
         /// disable event (not reported)
         pub const DISABLE = 0x0008;
+        /// enable _ONESHOT and force trigger
+        pub const FORCEONESHOT = 0x0100;
+        /// do not update the udata field
+        pub const KEEPUDATA = 0x0200;
         /// only report one occurrence
         pub const ONESHOT = 0x0010;
         /// clear event state after reporting
         pub const CLEAR = 0x0020;
-        /// error, event data contains errno
-        pub const ERROR = 0x4000;
         /// force immediate event output
         /// ... with or without ERROR
         /// ... use KEVENT_FLAG_ERROR_EVENTS
@@ -9839,6 +9846,18 @@ pub const EV = switch (native_os) {
         pub const RECEIPT = 0x0040;
         /// disable event after reporting
         pub const DISPATCH = 0x0080;
+        /// reserved by system
+        pub const SYSFLAGS = 0xF000;
+        /// note should be dropped
+        pub const DROP = 0x1000;
+        /// filter-specific flag 1
+        pub const FLAG1 = 0x2000;
+        /// filter-specific flag 2
+        pub const FLAG2 = 0x4000;
+        /// EOF detected (return value)
+        pub const EOF = 0x8000;
+        /// error, event data contains errno (return value)
+        pub const ERROR = 0x4000;
     },
     .openbsd => struct {
         pub const ADD = 0x0001;
@@ -9962,6 +9981,7 @@ pub const EVFILT = switch (native_os) {
         pub const EMPTY = 9;
     },
     .freebsd => struct {
+        // https://cgit.freebsd.org/src/tree/sys/sys/event.h
         pub const READ = -1;
         pub const WRITE = -2;
         /// attached to aio requests
@@ -9978,12 +9998,18 @@ pub const EVFILT = switch (native_os) {
         pub const PROCDESC = -8;
         /// Filesystem events
         pub const FS = -9;
+        /// attached to lio requests
         pub const LIO = -10;
         /// User events
         pub const USER = -11;
         /// Sendfile events
         pub const SENDFILE = -12;
+        /// empty send socket buf
         pub const EMPTY = -13;
+        /// attached to struct prison
+        pub const JAIL = -14;
+        /// attached to jail descriptors
+        pub const JAILDESC = -15;
     },
     .openbsd => struct {
         pub const READ = -1;
@@ -10002,6 +10028,7 @@ pub const EVFILT = switch (native_os) {
 
 pub const NOTE = switch (native_os) {
     .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct {
+        // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h
         /// On input, TRIGGER causes the event to be triggered for output.
         pub const TRIGGER = 0x01000000;
         /// ignore input fflags
@@ -10033,7 +10060,7 @@ pub const NOTE = switch (native_os) {
         pub const RENAME = 0x00000020;
         /// vnode access was revoked
         pub const REVOKE = 0x00000040;
-        /// No specific vnode event: to test for EVFILT_READ      activation
+        /// No specific vnode event: to test for EVFILT_READ activation
         pub const NONE = 0x00000080;
         /// vnode was unlocked by flock(2)
         pub const FUNLOCK = 0x00000100;
@@ -10045,7 +10072,7 @@ pub const NOTE = switch (native_os) {
         pub const EXEC = 0x20000000;
         /// shared with EVFILT_SIGNAL
         pub const SIGNAL = 0x08000000;
-        /// exit status to be returned, valid for child       process only
+        /// exit status to be returned, valid for child process only
         pub const EXITSTATUS = 0x04000000;
         /// provide details on reasons for exit
         pub const EXIT_DETAIL = 0x02000000;
@@ -10056,11 +10083,11 @@ pub const NOTE = switch (native_os) {
         pub const EXIT_DECRYPTFAIL = 0x00010000;
         pub const EXIT_MEMORY = 0x00020000;
         pub const EXIT_CSERROR = 0x00040000;
-        /// will react on memory          pressure
+        /// will react on memory pressure
         pub const VM_PRESSURE = 0x80000000;
-        /// will quit on memory       pressure, possibly after cleaning up dirty state
+        /// will quit on memory pressure, possibly after cleaning up dirty state
         pub const VM_PRESSURE_TERMINATE = 0x40000000;
-        /// will quit immediately on      memory pressure
+        /// will quit immediately on memory pressure
         pub const VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000;
         /// there was an error
         pub const VM_ERROR = 0x10000000;
@@ -10078,6 +10105,9 @@ pub const NOTE = switch (native_os) {
         pub const CRITICAL = 0x00000020;
         /// system does maximum timer coalescing
         pub const BACKGROUND = 0x00000040;
+        /// with ABSOLUTE: causes the timer to continue to tick across sleep, still uses gettimeofday epoch
+        /// with MACHTIME and ABSOLUTE: uses mach continuous time epoch
+        /// without ABSOLUTE: continues to tick across sleep
         pub const MACH_CONTINUOUS_TIME = 0x00000080;
         /// data is mach absolute time units
         pub const MACHTIME = 0x00000100;
-- 
2.54.0


From a3ff721b3d056f863cbcd2e9e94cc89d6c82a6ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sun, 2 Aug 2026 13:08:04 +0200
Subject: [PATCH 112/215] llvm: don't append OS version to triple for
 amdgcn-amdhsa

closes https://codeberg.org/ziglang/zig/issues/36355
---
 src/codegen/llvm.zig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 9e9b32eeab4c25e5d01ecc9bd3fdd80c5703c704..ec2427ee0e913cf711f01601a53a77b23315da30 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -263,7 +263,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
         => {},
         .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {
             try llvm_triple.print("p{d}", .{ver.min.minor});
-        } else {
+        } else if (target.os.tag != .amdhsa) {
             try llvm_triple.print("{d}.{d}.{d}", .{
                 ver.min.major,
                 ver.min.minor,
-- 
2.54.0


From b8431819b27d91b8c1dd367a0ce28d8ed4ec2ea8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sun, 2 Aug 2026 13:08:50 +0200
Subject: [PATCH 113/215] compiler: allow dynamic linking for amdgcn

closes https://codeberg.org/ziglang/zig/issues/36343
---
 src/target.zig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/target.zig b/src/target.zig
index 00a7e498d95fba989875fb9c96aa93273c51ac58..c64fd988cf4de9c881a8e79041ea8f7b80b099d0 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -12,7 +12,6 @@ pub const default_stack_protector_buffer_size = 4;
 
 pub fn canDynamicLink(target: *const std.Target) bool {
     return switch (target.cpu.arch) {
-        .amdgcn,
         .bpfeb,
         .bpfel,
         .nvptx,
-- 
2.54.0


From 1b7b856a810708ecfc8f78298cdd0a76315e8578 Mon Sep 17 00:00:00 2001
From: Ignacio Ibarra 
Date: Wed, 29 Jul 2026 22:33:30 -0400
Subject: [PATCH 114/215] llvm: workaround NVPTX alias restriction on kernel
 exports

Solves the LLVM error "NVPTX aliasee must be a non-kernel function definition."
on nvptx(64) targets, by renaming the llvm global directly to the first export.
---
 src/codegen/llvm.zig | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 9e9b32eeab4c25e5d01ecc9bd3fdd80c5703c704..9bd2aac248701b88dd1c5b1d57853d6b441c2524 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1506,6 +1506,9 @@ pub const Object = struct {
             variable.setSection(try o.builder.string(section_slice), &o.builder);
         }
 
+        const arch = comp.root_mod.resolved_target.result.cpu.arch;
+        const is_nvptx = arch == .nvptx or arch == .nvptx64;
+
         const llvm_global_ty = llvm_global.typeOf(&o.builder);
 
         // All exports are represented as aliases to the original global.
@@ -1513,7 +1516,7 @@ pub const Object = struct {
         // TODO: we currently do not delete old exports. To do that we'll need to track which
         // globals actually *are* exports.
 
-        for (export_indices) |export_idx| {
+        for (export_indices, 0..) |export_idx, export_i| {
             const exp = export_idx.ptr(zcu);
             const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));
 
@@ -1524,6 +1527,15 @@ pub const Object = struct {
             // The name, aliasee, and type will be set within this block. Other properties of the
             // alias will be set below.
             const alias_global: Builder.Global.Index = global: {
+
+                // WORKAROUND (see https://github.com/llvm/llvm-project/issues/213504)
+                // LLVM throws "NVPTX aliasee must be a non-kernel function definition"
+                // if we try to alias a kernel, so we just rename the global directly.
+                if (is_nvptx and export_i == 0) {
+                    try llvm_global.rename(exp_name, &o.builder);
+                    break :global llvm_global;
+                }
+
                 const existing_global = o.builder.getGlobal(exp_name) orelse {
                     // There is no existing global with this name, so make a new alias.
                     const alias = try o.builder.addAlias(
-- 
2.54.0


From 539bdfc46ff75a4a4febb97a7700ade393c1cb22 Mon Sep 17 00:00:00 2001
From: Theo Fabi 
Date: Fri, 24 Jul 2026 12:31:28 -0400
Subject: [PATCH 115/215] debug.MachOFile: handle truncated dwarf section names

Some dwarf section names like __debug_str_offsets don't fit in a Mach-O
sectname buffer, so their actual name in Mach-O binaries is truncated.

When searching for sections to load an object file's debug info, we now
compare the section name with the truncated name. Before, the full name
was checked, so we would unconditionally skip __debug_str_offsets dwarf
sections.
---
 lib/std/debug/MachOFile.zig | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig
index 158e908183715fd06876b1191d4cad0cf2cd5301..8b35d7541d05caae74e065d6146ebbffd4e8d3e4 100644
--- a/lib/std/debug/MachOFile.zig
+++ b/lib/std/debug/MachOFile.zig
@@ -504,8 +504,11 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
 
         if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue;
 
-        const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |section_name, i| {
-            if (mem.eql(u8, "__" ++ section_name, sect.sectName())) break i;
+        const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |field_name, i| {
+            const section_name_long = "__" ++ field_name;
+            // Some dwarf section names don't fit in the `sectname` buffer, so they are truncated.
+            const section_name_trunc = section_name_long[0..@min(section_name_long.len, sect.sectname.len)];
+            if (mem.eql(u8, section_name_trunc, sect.sectName())) break i;
         } else continue;
 
         if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO;
-- 
2.54.0


From e69d19d1ee06ebb50af191d2911355d817eb1249 Mon Sep 17 00:00:00 2001
From: Justus Klausecker 
Date: Sun, 17 May 2026 19:11:16 +0200
Subject: [PATCH 116/215] Sema: allow direct dereference of comptime-known
 slices

A comptime-known `[]T` should behave as similarly as possible to a comptime-
known `*[n]T`. It is now possible to directly dereference both to an array.

Also adds checks for slices with undefined length in code paths where a
slice is dereferenced as an array which would previously crash.
---
 lib/std/zig/Zir.zig                           |  2 +-
 src/Sema.zig                                  | 68 ++++++++++---------
 src/Zcu/PerThread.zig                         | 19 ++++++
 test/behavior/slice.zig                       | 44 ++++++++++++
 .../deref_slice_and_get_len_field.zig         |  2 +-
 .../deref_slice_with_undef_len.zig            | 23 +++++++
 .../compile_errors/dereference_slice.zig      |  2 +-
 7 files changed, 126 insertions(+), 34 deletions(-)
 create mode 100644 test/cases/compile_errors/deref_slice_with_undef_len.zig

diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig
index 1ec523e8694eb854692a94fbe560e25b11046a34..d79251c7db366d256a43487c0722c6810050ab31 100644
--- a/lib/std/zig/Zir.zig
+++ b/lib/std/zig/Zir.zig
@@ -584,7 +584,7 @@ pub const Inst = struct {
         /// containing the instruction.
         /// Uses the `un_tok` union field.
         ref,
-        /// Implements the dereference operand (`.*`). Checks that operand is a pointer
+        /// Implements the dereference operator (`.*`). Checks that operand is a pointer
         /// that supports being directly dereferenced.
         /// Uses the `un_node` union field.
         deref,
diff --git a/src/Sema.zig b/src/Sema.zig
index ba5ad7eb1566c69ee5377a8269d3ac512e073d31..c81b50fb18214901ef61e9a4a8e07903fd0240c6 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in
     });
 }
 
+pub fn failWithUndefSliceLen(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {
+    return sema.fail(block, src, "use of slice with undefined length here causes illegal behavior", .{});
+}
+
 pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError {
     return sema.fail(block, src, "division by zero here causes illegal behavior", .{});
 }
@@ -3113,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
     try sema.validateDeref(block, src, operand, operand_ty);
 
     const ptr_info = operand_ty.ptrInfo(zcu);
-    return switch (ptr_info.flags.size) {
-        .many, .slice => unreachable, // cannot be dereferenced
-        .c => single_ptr: {
+    return single_ptr: switch (ptr_info.flags.size) {
+        .many => unreachable, // cannot be dereferenced directly
+        .slice => {
+            const slice_val = sema.resolveValue(operand).?;
+            const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice;
+            break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice));
+        },
+        .c => {
             const single_ptr_ty = try pt.ptrType(p: {
                 var p = ptr_info;
                 p.flags.size = .one;
@@ -3149,18 +3158,26 @@ fn validateDeref(
 ) CompileError!void {
     const pt = sema.pt;
     const zcu = pt.zcu;
+    const ip = &zcu.intern_pool;
     if (ty.zigTypeTag(zcu) != .pointer) {
         return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)});
-    } else switch (ty.ptrSize(zcu)) {
-        .one, .c => {},
+    }
+    const size = ty.ptrSize(zcu);
+    switch (size) {
         .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}),
-        .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{ty.fmt(pt)}),
+        .one, .c, .slice => {},
     }
     if (sema.resolveValue(ref)) |val| {
         // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
         if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) {
             return sema.fail(block, src, "cannot dereference undefined value", .{});
         }
+        // We need a defined slice length for the array type the slice should be dereferenced to.
+        if (size == .slice and ip.indexToKey(val.toIntern()).slice.len == .undef_usize) {
+            return sema.fail(block, src, "cannot dereference slice with undefined length", .{});
+        }
+    } else if (size == .slice) {
+        return sema.fail(block, src, "index syntax required to access runtime-known slice", .{});
     }
 }
 
@@ -13570,14 +13587,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu))
                 try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src
             else if (lhs_ty.isSlice(zcu))
-                try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :rs lhs_src
+                try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src
             else
                 lhs_val;
 
             const rhs_sub_val = if (rhs_ty.isSinglePointer(zcu))
                 try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src
             else if (rhs_ty.isSlice(zcu))
-                try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val) orelse break :rs rhs_src
+                try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src
             else
                 rhs_val;
 
@@ -30940,8 +30957,11 @@ fn analyzeLoad(
     };
 
     if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
-        if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
-            return Air.internedToRef(elem_val.toIntern());
+        if (switch (ptr_ty.ptrSize(zcu)) {
+            .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val, ptr_ty),
+            else => try sema.pointerDeref(block, src, ptr_val, ptr_ty),
+        }) |elem_val| {
+            return .fromValue(elem_val);
         }
     }
 
@@ -34558,7 +34578,7 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool {
         .slice => {
             // If the slice contents are runtime-known, reification will fail later on with a
             // specific error message.
-            const arr = try sema.maybeDerefSliceAsArray(block, src, val) orelse return false;
+            const arr = try sema.maybeDerefSliceAsArray(block, src, val, val.typeOf(zcu)) orelse return false;
             return sema.anyUndef(block, src, arr);
         },
         .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
@@ -34599,7 +34619,7 @@ fn derefSliceAsArray(
     /// being comptime-resolved is that the block is being comptime-evaluated.
     reason: ?ComptimeReason,
 ) CompileError!Value {
-    return try sema.maybeDerefSliceAsArray(block, src, slice_val) orelse {
+    return try sema.maybeDerefSliceAsArray(block, src, slice_val, slice_val.typeOf(sema.pt.zcu)) orelse {
         return sema.failWithNeededComptime(block, src, reason);
     };
 }
@@ -34612,37 +34632,23 @@ fn maybeDerefSliceAsArray(
     block: *Block,
     src: LazySrcLoc,
     slice_val: Value,
+    slice_ty: Type,
 ) CompileError!?Value {
     const pt = sema.pt;
     const zcu = pt.zcu;
-    const ip = &zcu.intern_pool;
-    const slice_ty = slice_val.typeOf(zcu);
-    assert(slice_ty.zigTypeTag(zcu) == .pointer);
     switch (slice_ty.ptrInfo(zcu).flags.size) {
         .slice => {},
         .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
         .many, .c => unreachable,
     }
-    const slice = switch (ip.indexToKey(slice_val.toIntern())) {
+    const slice = switch (zcu.intern_pool.indexToKey(slice_val.toIntern())) {
         .undef => return sema.failWithUseOfUndef(block, src, null),
         .slice => |slice| slice,
         else => unreachable,
     };
-    const elem_ty = Type.fromInterned(slice.ty).childType(zcu);
-    const len = Value.fromInterned(slice.len).toUnsignedInt(zcu);
-    const array_ty = try pt.arrayType(.{
-        .child = elem_ty.toIntern(),
-        .len = len,
-    });
-    const ptr_ty = try pt.ptrType(p: {
-        var p = Type.fromInterned(slice.ty).ptrInfo(zcu);
-        p.flags.size = .one;
-        p.child = array_ty.toIntern();
-        p.sentinel = .none;
-        break :p p;
-    });
-    const casted_ptr = try pt.getCoerced(Value.fromInterned(slice.ptr), ptr_ty);
-    return sema.pointerDeref(block, src, casted_ptr, ptr_ty);
+    if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src);
+    const casted_ptr = try pt.sliceToArrayPtr(slice);
+    return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu));
 }
 
 fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void {
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index 4092f27b8b7ca16a56b412805779584b801561f9..bf72a73851b39910c3d43250a286efa98f780b20 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -3498,6 +3498,25 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err
     return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name));
 }
 
+/// Asserts that `slice.len` is *not* undef.
+pub fn sliceToArrayPtr(pt: Zcu.PerThread, slice: InternPool.Key.Slice) Allocator.Error!Value {
+    const zcu = pt.zcu;
+    const slice_info = Type.fromInterned(slice.ty).ptrInfo(zcu);
+    const array_ty = try pt.arrayType(.{
+        .len = Value.fromInterned(slice.len).toUnsignedInt(zcu),
+        .child = slice_info.child,
+        .sentinel = slice_info.sentinel,
+    });
+    const ptr_ty = try pt.ptrType(ptr_info: {
+        var ptr_info = slice_info;
+        ptr_info.flags.size = .one;
+        ptr_info.child = array_ty.toIntern();
+        ptr_info.sentinel = .none;
+        break :ptr_info ptr_info;
+    });
+    return pt.getCoerced(.fromInterned(slice.ptr), ptr_ty);
+}
+
 /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.
 /// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.
 fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, file: *Zcu.File) void {
diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig
index f1efaa9f43686a0d3570c7e33c335a0f1e6c84e3..7021b76c69dff0f63e1bb26165aa5fae57e6a1d6 100644
--- a/test/behavior/slice.zig
+++ b/test/behavior/slice.zig
@@ -1089,3 +1089,47 @@ test "slice field alignment" {
     var arr: [10]u8 = @splat(0);
     try S.doTheTest(&&arr);
 }
+
+test "directly deref slice with comptime-known length" {
+    {
+        const slice: []const u16 = &.{ 1, 2, 3 };
+        const array = slice.*;
+
+        comptime assert(@TypeOf(array) == [3]u16);
+        comptime assert(array[0] == 1);
+        comptime assert(array[1] == 2);
+        comptime assert(array[2] == 3);
+    }
+    {
+        const slice: [:0]const u16 = &.{ 1, 2, 3 };
+        const array = slice.*;
+
+        comptime assert(@TypeOf(array) == [3:0]u16);
+        comptime assert(array[0] == 1);
+        comptime assert(array[1] == 2);
+        comptime assert(array[2] == 3);
+        comptime assert(array[3] == 0);
+    }
+}
+
+test "address of dereferenced slice is array pointer" {
+    {
+        const slice: []const u16 = &.{ 1, 2, 3 };
+        const array_ptr = &slice.*;
+
+        comptime assert(@TypeOf(array_ptr) == *const [3]u16);
+        comptime assert(array_ptr[0] == 1);
+        comptime assert(array_ptr[1] == 2);
+        comptime assert(array_ptr[2] == 3);
+    }
+    {
+        const slice: [:0]const u16 = &.{ 1, 2, 3 };
+        const array_ptr = &slice.*;
+
+        comptime assert(@TypeOf(array_ptr) == *const [3:0]u16);
+        comptime assert(array_ptr[0] == 1);
+        comptime assert(array_ptr[1] == 2);
+        comptime assert(array_ptr[2] == 3);
+        comptime assert(array_ptr[3] == 0);
+    }
+}
diff --git a/test/cases/compile_errors/deref_slice_and_get_len_field.zig b/test/cases/compile_errors/deref_slice_and_get_len_field.zig
index 57459f488eca026cb7a4f27bc82d7d2ef13e4c5b..8917259ccbce1c5c31d13ae9722cc38d6fb7b03f 100644
--- a/test/cases/compile_errors/deref_slice_and_get_len_field.zig
+++ b/test/cases/compile_errors/deref_slice_and_get_len_field.zig
@@ -6,4 +6,4 @@ export fn entry() void {
 
 // error
 //
-// :3:10: error: index syntax required for slice type '[]u8'
+// :3:10: error: index syntax required to access runtime-known slice
diff --git a/test/cases/compile_errors/deref_slice_with_undef_len.zig b/test/cases/compile_errors/deref_slice_with_undef_len.zig
new file mode 100644
index 0000000000000000000000000000000000000000..e3dcd2e158719cff1b14213c5b1cc2c05ef333e4
--- /dev/null
+++ b/test/cases/compile_errors/deref_slice_with_undef_len.zig
@@ -0,0 +1,23 @@
+export fn entry2() void {
+    comptime var slice: []const u16 = &.{ 1, 2, 3 };
+    slice.len = undefined;
+    _ = slice.*;
+}
+
+export fn entry3() void {
+    comptime var slice: []const u16 = &.{ 1, 2, 3 };
+    slice.len = undefined;
+    _ = &slice.*;
+}
+
+export fn entry4() void {
+    comptime var slice: []const u8 = "hello";
+    slice.len = undefined;
+    @compileError(slice);
+}
+
+// error
+//
+// :4:14: error: cannot dereference slice with undefined length
+// :10:15: error: cannot dereference slice with undefined length
+// :16:19: error: use of slice with undefined length here causes illegal behavior
diff --git a/test/cases/compile_errors/dereference_slice.zig b/test/cases/compile_errors/dereference_slice.zig
index e2221ea609bf5c36a0304360dabd2e35aedd998f..73db0ff950e63718421846e645aba6ac7f19a23f 100644
--- a/test/cases/compile_errors/dereference_slice.zig
+++ b/test/cases/compile_errors/dereference_slice.zig
@@ -7,4 +7,4 @@ comptime {
 
 // error
 //
-// :2:13: error: index syntax required for slice type '[]i32'
+// :2:13: error: index syntax required to access runtime-known slice
-- 
2.54.0


From adef113102f7b5c55f502c9b4ac58f61349eab1d Mon Sep 17 00:00:00 2001
From: Justus Klausecker 
Date: Tue, 16 Jun 2026 19:23:46 +0200
Subject: [PATCH 117/215] Sema: allow coercion from []T to *[n]T if length is
 comptime-known

A comptime-known `[]T` should behave as similarly as possible to a comptime-
known `*[n]T`. It is now possible to coerce the former to the latter if
their length matches.
---
 src/Sema.zig                                  | 105 ++++++++++++++++--
 test/behavior/slice.zig                       |  38 +++++++
 ...inters_with_uncoercable_child_pointers.zig |  14 +++
 .../compile_errors/slice_to_array_pointer.zig |  70 ++++++++++++
 4 files changed, 220 insertions(+), 7 deletions(-)
 create mode 100644 test/cases/compile_errors/slice_to_array_pointer.zig

diff --git a/src/Sema.zig b/src/Sema.zig
index c81b50fb18214901ef61e9a4a8e07903fd0240c6..29baca211860aee36f398f78a43792926a5896fa 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -28258,9 +28258,94 @@ fn coerceExtra(
                     },
                     else => {},
                 },
-                .one => {},
+                // []T to *[n]T
+                .one => slice_to_array_ptr: {
+                    if (!inst_ty.isSlice(zcu)) break :slice_to_array_ptr;
+                    if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :slice_to_array_ptr;
+                    const array_ty: Type = .fromInterned(dest_info.child);
+                    if (array_ty.zigTypeTag(zcu) != .array) break :slice_to_array_ptr;
+                    const inst_val = maybe_inst_val orelse {
+                        if (!opts.report_err) return error.NotCoercible;
+                        return sema.fail(
+                            block,
+                            inst_src,
+                            "coercion from slice to array pointer type '{f}' requires length to be known at compile-time",
+                            .{dest_ty.fmt(pt)},
+                        );
+                    };
+
+                    const slice: InternPool.Key.Slice = slice: {
+                        switch (ip.indexToKey(inst_val.toIntern())) {
+                            .undef => {},
+                            .slice => |slice| if (slice.len != .undef_usize) break :slice slice,
+                            else => unreachable,
+                        }
+                        if (!opts.report_err) return error.NotCoercible;
+                        return sema.failWithOwnedErrorMsg(block, msg: {
+                            const msg = try sema.errMsg(inst_src, "slice with undefined length cannot cast into array pointer type '{f}'", .{
+                                dest_ty.fmt(pt),
+                            });
+                            errdefer msg.destroy(gpa);
+                            try sema.errNote(inst_src, msg, "length of slice must be defined and match length of array type", .{});
+                            break :msg msg;
+                        });
+                    };
+                    const slice_len = Value.fromInterned(slice.len).toUnsignedInt(zcu);
+                    if (array_ty.arrayLen(zcu) != slice_len) {
+                        if (!opts.report_err) return error.NotCoercible;
+                        return sema.failWithOwnedErrorMsg(block, msg: {
+                            const msg = try sema.errMsg(inst_src, "slice of length {d} cannot cast into array pointer type '{f}'", .{
+                                slice_len, dest_ty.fmt(pt),
+                            });
+                            errdefer msg.destroy(gpa);
+                            try sema.errNote(inst_src, msg, "length of slice must match length of array type", .{});
+                            break :msg msg;
+                        });
+                    }
+
+                    const inst_elem_ty = inst_ty.childType(zcu);
+                    const dest_elem_ty = array_ty.childType(zcu);
+                    const dest_is_mut = !dest_info.flags.is_const;
+                    switch (try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) {
+                        .ok => {},
+                        else => |elem_res| {
+                            in_memory_result = .{ .ptr_child = .{
+                                .child = try elem_res.dupe(sema.arena),
+                                .actual = inst_elem_ty,
+                                .wanted = dest_elem_ty,
+                            } };
+                            break :slice_to_array_ptr;
+                        },
+                    }
+
+                    if (array_ty.sentinel(zcu)) |array_sentinel| {
+                        if (inst_ty.sentinel(zcu)) |slice_sentinel| {
+                            if (array_sentinel.toIntern() !=
+                                (try pt.getCoerced(slice_sentinel, dest_elem_ty)).toIntern())
+                            {
+                                in_memory_result = .{ .ptr_sentinel = .{
+                                    .actual = slice_sentinel,
+                                    .wanted = array_sentinel,
+                                    .ty = dest_elem_ty,
+                                } };
+                                break :slice_to_array_ptr;
+                            }
+                        } else {
+                            in_memory_result = .{ .ptr_sentinel = .{
+                                .actual = .@"unreachable",
+                                .wanted = array_sentinel,
+                                .ty = dest_elem_ty,
+                            } };
+                            break :slice_to_array_ptr;
+                        }
+                    }
+
+                    const array_ptr = try pt.sliceToArrayPtr(slice);
+                    return sema.coerceCompatiblePtrs(block, dest_ty, .fromValue(array_ptr), inst_src);
+                },
                 .slice => to_slice: {
                     if (inst_ty.zigTypeTag(zcu) == .array) {
+                        if (!opts.report_err) return error.NotCoercible;
                         return sema.fail(
                             block,
                             inst_src,
@@ -28288,6 +28373,7 @@ fn coerceExtra(
 
                     // pointer to tuple to slice
                     if (!dest_info.flags.is_const) {
+                        if (!opts.report_err) return error.NotCoercible;
                         const err_msg = err_msg: {
                             const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});
                             errdefer err_msg.destroy(sema.gpa);
@@ -28383,6 +28469,7 @@ fn coerceExtra(
                 if (maybe_inst_val) |val| {
                     const result_val = try val.floatCast(dest_ty, pt);
                     if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) {
+                        if (!opts.report_err) return error.NotCoercible;
                         return sema.fail(
                             block,
                             inst_src,
@@ -28440,12 +28527,15 @@ fn coerceExtra(
                         break :fits result_big_int.toConst().eql(operand_big_int);
                     },
                 };
-                if (!fits) return sema.fail(
-                    block,
-                    inst_src,
-                    "type '{f}' cannot represent integer value '{f}'",
-                    .{ dest_ty.fmt(pt), val.fmtValue(pt) },
-                );
+                if (!fits) {
+                    if (!opts.report_err) return error.NotCoercible;
+                    return sema.fail(
+                        block,
+                        inst_src,
+                        "type '{f}' cannot represent integer value '{f}'",
+                        .{ dest_ty.fmt(pt), val.fmtValue(pt) },
+                    );
+                }
                 return .fromValue(result_val);
             },
             else => {},
@@ -28456,6 +28546,7 @@ fn coerceExtra(
                 const val = sema.resolveValue(inst).?;
                 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
                 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
+                    if (!opts.report_err) return error.NotCoercible;
                     return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
                         string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
                     });
diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig
index 7021b76c69dff0f63e1bb26165aa5fae57e6a1d6..247c3d1be8f3a15ab8b53f9d0a47f2bdea02cc4f 100644
--- a/test/behavior/slice.zig
+++ b/test/behavior/slice.zig
@@ -1133,3 +1133,41 @@ test "address of dereferenced slice is array pointer" {
         comptime assert(array_ptr[3] == 0);
     }
 }
+
+test "coerce slice with comptime-known length to array pointer" {
+    {
+        const slice: []const u16 = &.{ 1, 2, 3 };
+        const array_ptr: *const [3]u16 = slice;
+
+        comptime assert(array_ptr[0] == 1);
+        comptime assert(array_ptr[1] == 2);
+        comptime assert(array_ptr[2] == 3);
+    }
+    {
+        const slice: [:0]const u16 = &.{ 1, 2, 3 };
+        const array_ptr: *const [3:0]u16 = slice;
+
+        comptime assert(array_ptr[0] == 1);
+        comptime assert(array_ptr[1] == 2);
+        comptime assert(array_ptr[2] == 3);
+        comptime assert(array_ptr[3] == 0);
+    }
+    {
+        const slice: [:0]const u16 = &.{ 1, 2, 3 };
+        const array_ptr: *const [3]u16 = slice;
+
+        comptime assert(array_ptr[0] == 1);
+        comptime assert(array_ptr[1] == 2);
+        comptime assert(array_ptr[2] == 3);
+    }
+}
+
+test "modify slice through coerced array pointer" {
+    comptime {
+        var array: [3]u16 = .{ 1, 2, 3 };
+        const slice: []u16 = &array;
+        const array_ptr: *[3]u16 = slice;
+        array_ptr[2] = 0;
+        assert(slice[2] == 0);
+    }
+}
diff --git a/test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig b/test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig
index bef21b2777ff5503899741f812dcbf7bc3b61b68..77f48e656c0a81c94353a555542a4b3e73ace4e8 100644
--- a/test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig
+++ b/test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig
@@ -28,6 +28,16 @@ export fn entry5() void {
     _ = q;
 }
 
+export fn entry6(p: **[3]u8) void {
+    const q: *[]u8 = p;
+    _ = q;
+}
+
+export fn entry7(p: *[]u8) void {
+    const q: **[3]u8 = p;
+    _ = q;
+}
+
 // error
 //
 // :3:22: error: expected type '**i32', found '**u32'
@@ -50,3 +60,7 @@ export fn entry5() void {
 // :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8'
 // :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8'
 // :27:24: note: source array cannot be guaranteed to maintain '42' sentinel
+// :32:22: error: expected type '*[]u8', found '**[3]u8'
+// :32:22: note: pointer type child '*[3]u8' cannot cast into pointer type child '[]u8'
+// :37:24: error: expected type '**[3]u8', found '*[]u8'
+// :37:24: note: pointer type child '[]u8' cannot cast into pointer type child '*[3]u8'
diff --git a/test/cases/compile_errors/slice_to_array_pointer.zig b/test/cases/compile_errors/slice_to_array_pointer.zig
new file mode 100644
index 0000000000000000000000000000000000000000..9e4750a3645820240e505ab6d471be99d18877cc
--- /dev/null
+++ b/test/cases/compile_errors/slice_to_array_pointer.zig
@@ -0,0 +1,70 @@
+export fn entry1() void {
+    var array: [2]u16 = .{ 1, 2 };
+    const slice: []const u16 = &array;
+    foo(slice);
+}
+
+export fn entry2() void {
+    const slice: []const u16 = undefined;
+    foo(slice);
+}
+
+export fn entry3() void {
+    comptime var slice: []const u16 = &.{ 1, 2 };
+    slice.len = undefined;
+    foo(slice);
+}
+
+export fn entry4() void {
+    const slice: []const u16 = &.{ 1, 2, 3 };
+    foo(slice);
+}
+
+export fn entry5() void {
+    const slice: []const u8 = &.{ 1, 2 };
+    foo(slice);
+}
+
+fn foo(x: *const [2]u16) void {
+    _ = x;
+}
+
+export fn entry6() void {
+    const slice: [:0]const u16 = &.{ 1, 2, 3 };
+    bar(slice);
+}
+
+export fn entry7() void {
+    const slice: [:1]const u16 = &.{ 1, 2 };
+    bar(slice);
+}
+
+export fn entry8() void {
+    const slice: []const u16 = &.{ 1, 2 };
+    bar(slice);
+}
+
+fn bar(x: *const [2:0]u16) void {
+    _ = x;
+}
+
+// error
+//
+// :4:9: error: coercion from slice to array pointer type '*const [2]u16' requires length to be known at compile-time
+// :9:9: error: slice with undefined length cannot cast into array pointer type '*const [2]u16'
+// :9:9: note: length of slice must be defined and match length of array type
+// :15:9: error: slice with undefined length cannot cast into array pointer type '*const [2]u16'
+// :15:9: note: length of slice must be defined and match length of array type
+// :20:9: error: slice of length 3 cannot cast into array pointer type '*const [2]u16'
+// :20:9: note: length of slice must match length of array type
+// :25:9: error: expected type '*const [2]u16', found '[]const u8'
+// :25:9: note: pointer type child 'u8' cannot cast into pointer type child 'u16'
+// :28:11: note: parameter type declared here
+// :34:9: error: slice of length 3 cannot cast into array pointer type '*const [2:0]u16'
+// :34:9: note: length of slice must match length of array type
+// :39:9: error: expected type '*const [2:0]u16', found '[:1]const u16'
+// :39:9: note: pointer sentinel '1' cannot cast into pointer sentinel '0'
+// :47:11: note: parameter type declared here
+// :44:9: error: expected type '*const [2:0]u16', found '[]const u16'
+// :44:9: note: destination pointer requires '0' sentinel
+// :47:11: note: parameter type declared here
-- 
2.54.0


From 1dd69217729a6b95b4ac644cc5385a8b1bc6c044 Mon Sep 17 00:00:00 2001
From: Justus Klausecker 
Date: Sun, 2 Aug 2026 14:01:56 +0200
Subject: [PATCH 118/215] Sema: remove `slice_ty` param from
 `maybeDerefSliceAsArray` again

Instead compute it from `slice_val`.
---
 src/Sema.zig | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig
index 29baca211860aee36f398f78a43792926a5896fa..797bc299c34d8831c6a287106c35878a1d8f8152 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -13587,14 +13587,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu))
                 try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src
             else if (lhs_ty.isSlice(zcu))
-                try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src
+                try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :rs lhs_src
             else
                 lhs_val;
 
             const rhs_sub_val = if (rhs_ty.isSinglePointer(zcu))
                 try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src
             else if (rhs_ty.isSlice(zcu))
-                try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src
+                try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val) orelse break :rs rhs_src
             else
                 rhs_val;
 
@@ -31049,7 +31049,7 @@ fn analyzeLoad(
 
     if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
         if (switch (ptr_ty.ptrSize(zcu)) {
-            .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val, ptr_ty),
+            .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val),
             else => try sema.pointerDeref(block, src, ptr_val, ptr_ty),
         }) |elem_val| {
             return .fromValue(elem_val);
@@ -34669,7 +34669,7 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool {
         .slice => {
             // If the slice contents are runtime-known, reification will fail later on with a
             // specific error message.
-            const arr = try sema.maybeDerefSliceAsArray(block, src, val, val.typeOf(zcu)) orelse return false;
+            const arr = try sema.maybeDerefSliceAsArray(block, src, val) orelse return false;
             return sema.anyUndef(block, src, arr);
         },
         .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
@@ -34710,7 +34710,7 @@ fn derefSliceAsArray(
     /// being comptime-resolved is that the block is being comptime-evaluated.
     reason: ?ComptimeReason,
 ) CompileError!Value {
-    return try sema.maybeDerefSliceAsArray(block, src, slice_val, slice_val.typeOf(sema.pt.zcu)) orelse {
+    return try sema.maybeDerefSliceAsArray(block, src, slice_val) orelse {
         return sema.failWithNeededComptime(block, src, reason);
     };
 }
@@ -34723,10 +34723,11 @@ fn maybeDerefSliceAsArray(
     block: *Block,
     src: LazySrcLoc,
     slice_val: Value,
-    slice_ty: Type,
 ) CompileError!?Value {
     const pt = sema.pt;
     const zcu = pt.zcu;
+    const slice_ty = slice_val.typeOf(zcu);
+    assert(slice_ty.zigTypeTag(zcu) == .pointer);
     switch (slice_ty.ptrInfo(zcu).flags.size) {
         .slice => {},
         .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
-- 
2.54.0


From 32ed280a9b7f16a48d970d06a27a26ee38c24ca1 Mon Sep 17 00:00:00 2001
From: Ben Burkert 
Date: Mon, 22 Sep 2025 06:30:23 -0400
Subject: [PATCH 119/215] zon: add fmt function

Add std.zon.fmt Formatter that formats any value via std.zon.stringify.
---
 lib/std/zon.zig | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/lib/std/zon.zig b/lib/std/zon.zig
index 969e0c8c761607a84871e2b443aed80ff6c83ff8..7a979beaad4f7a2c5c49e854dd7f17048b76ce48 100644
--- a/lib/std/zon.zig
+++ b/lib/std/zon.zig
@@ -37,10 +37,51 @@
 //! ZON does not have syntax for pointers, but the parsers will allocate as needed to match the
 //! given Zig types. Similarly, the serializer will traverse pointers.
 
+const std = @import("std");
+
 pub const parse = @import("zon/parse.zig");
 pub const stringify = @import("zon/stringify.zig");
 pub const Serializer = @import("zon/Serializer.zig");
 
+/// Returns a formatter that formats the given value using stringify.
+pub fn fmt(value: anytype, options: stringify.SerializeOptions) Formatter(@TypeOf(value)) {
+    return Formatter(@TypeOf(value)){ .value = value, .options = options };
+}
+
+test fmt {
+    const expectFmt = std.testing.expectFmt;
+    try expectFmt("123", "{f}", .{fmt(@as(u32, 123), .{})});
+    try expectFmt(
+        \\.{
+        \\    .num = 927,
+        \\    .msg = "hello",
+        \\    .sub = .{ .mybool = true },
+        \\}
+    , "{f}", .{fmt(struct {
+        num: u32,
+        msg: []const u8,
+        sub: struct {
+            mybool: bool,
+        },
+    }{
+        .num = 927,
+        .msg = "hello",
+        .sub = .{ .mybool = true },
+    }, .{})});
+}
+
+/// Formats the given value using stringify.
+pub fn Formatter(comptime T: type) type {
+    return struct {
+        value: T,
+        options: stringify.SerializeOptions,
+
+        pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
+            try stringify.serialize(self.value, self.options, writer);
+        }
+    };
+}
+
 test {
     _ = parse;
     _ = stringify;
-- 
2.54.0


From ad6a79f327f6762baf9661341330c5a190c6d718 Mon Sep 17 00:00:00 2001
From: Elaine Gibson 
Date: Mon, 3 Aug 2026 09:59:04 +0100
Subject: [PATCH 120/215] std.c.haiku: cleanup

---
 lib/std/Thread.zig  |  7 ++--
 lib/std/c.zig       | 14 ++------
 lib/std/c/haiku.zig | 80 +++++++--------------------------------------
 3 files changed, 17 insertions(+), 84 deletions(-)

diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index ad3fc383d9f5564d88ffec430d390f8cb75fd9bb..0cc439d07da7d8a6c0de39a65bf83800ea9b6992 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -719,10 +719,9 @@ const PosixThreadImpl = struct {
             },
             .haiku => {
                 var system_info: std.c.system_info = undefined;
-                const rc = std.c.get_system_info(&system_info); // always returns B_OK
-                return switch (posix.errno(rc)) {
-                    .SUCCESS => @as(usize, @intCast(system_info.cpu_count)),
-                    else => |err| posix.unexpectedErrno(err),
+                return switch (std.c.get_system_info(&system_info)) {
+                    0 => @as(usize, @intCast(system_info.cpu_count)),
+                    else => error.Unexpected,
                 };
             },
             else => {
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 9f0feda6b37e4146bcebbdf26bdb97aefb4e7508..7d9a4b1d49caa7755db57477cdf9a6703ff3ecf2 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -11267,31 +11267,23 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;
 pub const taskid_t = illumos.taskid_t;
 pub const zoneid_t = illumos.zoneid_t;
 
+pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH;
 pub const DirEnt = haiku.DirEnt;
-pub const _get_next_area_info = haiku._get_next_area_info;
-pub const _get_next_image_info = haiku._get_next_image_info;
-pub const _get_team_info = haiku._get_team_info;
-pub const _kern_get_current_team = haiku._kern_get_current_team;
 pub const _kern_open_dir = haiku._kern_open_dir;
 pub const _kern_read_dir = haiku._kern_read_dir;
 pub const _kern_read_stat = haiku._kern_read_stat;
 pub const _kern_rewind_dir = haiku._kern_rewind_dir;
-pub const readv_pos = haiku.readv_pos;
-pub const writev_pos = haiku.writev_pos;
 pub const area_id = haiku.area_id;
-pub const area_info = haiku.area_info;
-pub const directory_which = haiku.directory_which;
-pub const find_directory = haiku.find_directory;
 pub const find_thread = haiku.find_thread;
 pub const get_system_info = haiku.get_system_info;
-pub const image_info = haiku.image_info;
 pub const port_id = haiku.port_id;
+pub const readv_pos = haiku.readv_pos;
 pub const sem_id = haiku.sem_id;
 pub const status_t = haiku.status_t;
 pub const system_info = haiku.system_info;
 pub const team_id = haiku.team_id;
-pub const team_info = haiku.team_info;
 pub const thread_id = haiku.thread_id;
+pub const writev_pos = haiku.writev_pos;
 
 pub const AUTH = openbsd.AUTH;
 pub const BI = openbsd.BI;
diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig
index dd599ca83735d3c470859cd5c59c73a167983e27..768935574d2912e79ea21f5bf1b4cd1f6f80b800 100644
--- a/lib/std/c/haiku.zig
+++ b/lib/std/c/haiku.zig
@@ -1,15 +1,8 @@
 const std = @import("../std.zig");
-const assert = std.debug.assert;
 const builtin = @import("builtin");
-const maxInt = std.math.maxInt;
-const iovec = std.posix.iovec;
-const iovec_const = std.posix.iovec_const;
-const socklen_t = std.c.socklen_t;
+const assert = std.debug.assert;
 const fd_t = std.c.fd_t;
 const off_t = std.c.off_t;
-const PATH_MAX = std.c.PATH_MAX;
-const uid_t = std.c.uid_t;
-const gid_t = std.c.gid_t;
 const dev_t = std.c.dev_t;
 const ino_t = std.c.ino_t;
 
@@ -17,53 +10,21 @@ comptime {
     assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.
 }
 
-pub extern "root" fn _errnop() *i32;
-pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
-pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;
-pub extern "root" fn get_system_info(system_info: *system_info) usize;
-pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;
-pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;
-pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;
-pub extern "root" fn _kern_get_current_team() team_id;
+pub const B_OS_NAME_LENGTH = 32;
+
 pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
 pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
 pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
 pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
+
+pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id;
+pub extern "root" fn get_system_info(info: *system_info) status_t;
+
+pub extern "root" fn _errnop() *i32;
+
 pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize;
 pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize;
 
-pub const area_info = extern struct {
-    area: u32,
-    name: [32]u8,
-    size: usize,
-    lock: u32,
-    protection: u32,
-    team_id: i32,
-    ram_size: u32,
-    copy_count: u32,
-    in_count: u32,
-    out_count: u32,
-    address: *anyopaque,
-};
-
-pub const image_info = extern struct {
-    id: u32,
-    image_type: u32,
-    sequence: i32,
-    init_order: i32,
-    init_routine: *anyopaque,
-    term_routine: *anyopaque,
-    device: i32,
-    node: i64,
-    name: [PATH_MAX]u8,
-    text: *anyopaque,
-    data: *anyopaque,
-    text_size: i32,
-    data_size: i32,
-    api_version: i32,
-    abi: i32,
-};
-
 pub const system_info = extern struct {
     boot_time: i64,
     cpu_count: u32,
@@ -86,31 +47,12 @@ pub const system_info = extern struct {
     max_teams: u32,
     used_teams: u32,
     kernel_name: [256]u8,
-    kernel_build_date: [32]u8,
-    kernel_build_time: [32]u8,
+    kernel_build_date: [B_OS_NAME_LENGTH]u8,
+    kernel_build_time: [B_OS_NAME_LENGTH]u8,
     kernel_version: i64,
     abi: u32,
 };
 
-pub const team_info = extern struct {
-    team_id: i32,
-    thread_count: i32,
-    image_count: i32,
-    area_count: i32,
-    debugger_nub_thread: i32,
-    debugger_nub_port: i32,
-    argc: i32,
-    args: [64]u8,
-    uid: uid_t,
-    gid: gid_t,
-};
-
-pub const directory_which = enum(i32) {
-    B_USER_SETTINGS_DIRECTORY = 0xbbe,
-
-    _,
-};
-
 pub const area_id = i32;
 pub const port_id = i32;
 pub const sem_id = i32;
-- 
2.54.0


From 845103fc9e9260e4aad188d029d06c61e631848f Mon Sep 17 00:00:00 2001
From: Elaine Gibson 
Date: Mon, 3 Aug 2026 11:52:08 +0100
Subject: [PATCH 121/215] std.Io.Threaded: implement park and unpark for haiku

---
 lib/std/Io/Threaded.zig | 74 ++++++++++++++++++++++++++++++++++++++---
 lib/std/c.zig           |  8 +++++
 lib/std/c/haiku.zig     |  7 ++++
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index c6473678a20326c606cabf29bd16e27af9ffd843..6f63dd5c9e4eaa601073addf93fe3fdfe9a5dc51 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -829,6 +829,7 @@ const Thread = struct {
     /// Always released when `Status.cancelation` is set to `.parked`.
     futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn,
     unpark_flag: UnparkFlag,
+    park_tid: if (ParkTid == std.Thread.Id) void else ParkTid,
 
     csprng: Csprng,
 
@@ -1220,7 +1221,7 @@ const Thread = struct {
                         parking_futex.removeCanceledWaiter(futex_waiter);
                     }
                     if (need_unpark_flag) setUnparkFlag(&thread.unpark_flag);
-                    unpark(&.{thread.id}, null);
+                    unpark(&.{if (ParkTid == std.Thread.Id) thread.id else thread.park_tid}, null);
                     return false;
                 },
 
@@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void {
         .cancel_protection = .unblocked,
         .futex_waiter = undefined,
         .unpark_flag = unpark_flag_init,
+        .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(),
         .csprng = .uninitialized,
     };
     Thread.current = &thread;
@@ -17430,6 +17432,7 @@ const use_parking_futex = switch (native_os) {
     .windows => true, // RtlWaitOnAddress is a userland implementation anyway
     .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now.
     .illumos => true, // Illumos has no futex mechanism
+    .haiku => true, // Haiku has no futex mechanism
     else => false,
 };
 const use_parking_sleep = switch (native_os) {
@@ -17475,7 +17478,7 @@ const parking_futex = struct {
     const Waiter = struct {
         node: std.DoublyLinkedList.Node,
         address: usize,
-        tid: std.Thread.Id,
+        tid: ParkTid,
         /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread
         /// which atomically updates it (to `.none` or `.canceling`) is responsible for:
         ///
@@ -17516,7 +17519,7 @@ const parking_futex = struct {
 
         // Put the threadlocal access outside of the critical section.
         const opt_thread = Thread.current;
-        const self_tid = if (opt_thread) |thread| thread.id else std.Thread.getCurrentId();
+        const self_tid = getParkTid();
 
         var waiter: Waiter = .{
             .node = undefined, // populated by list append
@@ -17764,7 +17767,12 @@ const parking_sleep = struct {
                 },
             }
         }
+
         // Uncancelable sleep; we expect not to be manually unparked.
+
+        // On systems where parking the thread requires a one-time setup operation (e.g. creating a
+        // semaphore), we need to ensure that setup is done before we call `park`.
+        _ = getParkTid();
         var dummy_flag: UnparkFlag = unpark_flag_init;
         if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) {
             unreachable; // unexpected unpark
@@ -17803,7 +17811,7 @@ const ParkingMutex = struct {
         /// Never modified once the `Waiter` is in the linked list.
         next: ?*Waiter,
         /// Never modified once the `Waiter` is in the linked list.
-        tid: std.Thread.Id,
+        tid: ParkTid,
     };
     fn lock(m: *ParkingMutex) void {
         state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case
@@ -17819,7 +17827,7 @@ const ParkingMutex = struct {
 
             .locked_once, _ => |last_state| {
                 const old_waiter = last_state.waiter();
-                const self_tid = if (Thread.current) |t| t.id else std.Thread.getCurrentId();
+                const self_tid = getParkTid();
                 var waiter: Waiter = .{
                     .next = old_waiter,
                     .unpark_flag = unpark_flag_init,
@@ -17947,9 +17955,36 @@ fn setUnparkFlag(f: *UnparkFlag) void {
 /// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be.
 const UnparkTid = switch (native_os) {
     .windows => usize,
+    else => ParkTid,
+};
+
+const ParkTid = switch (native_os) {
+    .haiku => std.c.sem_id,
     else => std.Thread.Id,
 };
 
+threadlocal var park_sem: std.c.sem_id = -1;
+
+fn getParkTid() ParkTid {
+    switch (native_os) {
+        .haiku => {
+            if (park_sem == -1) {
+                park_sem = std.c._kern_create_sem(0, null);
+                if (park_sem < 0) @panic("_kern_create_sem failed");
+                _ = std.c.on_exit_thread(destroyParkSem, null);
+            }
+            return park_sem;
+        },
+        else => {
+            return if (Thread.current) |thread| thread.id else std.Thread.getCurrentId();
+        },
+    }
+}
+
+fn destroyParkSem(_: ?*anyopaque) callconv(.c) void {
+    _ = std.c._kern_delete_sem(park_sem);
+}
+
 fn park(
     timeout: Io.Timeout,
     /// This value has no semantic effect, but may allow the OS to optimize the operation.
@@ -18015,6 +18050,27 @@ fn park(
             }
         },
         .illumos => @panic("TODO: illumos lwp_park"),
+        .haiku => {
+            const timeout_flags: u32, const timeout_us = switch (timeout) {
+                .none => .{ 0, 0 },
+                .deadline => |deadline| .{
+                    if (deadline.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
+                    deadline.raw.toMicroseconds(),
+                },
+                .duration => |duration| .{
+                    if (duration.clock == .real) std.c.B_ABSOLUTE_TIMEOUT | std.c.B_TIMEOUT_REAL_TIME_BASE else std.c.B_ABSOLUTE_TIMEOUT,
+                    nowPosix(duration.clock).addDuration(duration.raw).toMicroseconds(),
+                },
+            };
+            while (true) {
+                switch (std.c._kern_acquire_sem_etc(park_sem, 1, timeout_flags, timeout_us)) {
+                    0 => return,
+                    std.c.E.B_TIMED_OUT => return error.Timeout,
+                    std.c.E.B_INTERRUPTED => {},
+                    else => unreachable,
+                }
+            }
+        },
         else => comptime unreachable,
     }
 }
@@ -18057,6 +18113,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void {
             }
         },
         .illumos => @panic("TODO: illumos lwp_unpark"),
+        .haiku => {
+            for (tids) |tid| {
+                switch (std.c._kern_release_sem_etc(tid, 1, 0)) {
+                    0 => {},
+                    else => recoverableOsBugDetected(),
+                }
+            }
+        },
         else => comptime unreachable,
     }
 }
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 7d9a4b1d49caa7755db57477cdf9a6703ff3ecf2..a586082ec6e0318f54f80beaa3e2e49bf4bc0c5d 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) {
         pub const UNBLOCK = 2;
         pub const SETMASK = 3;
 
+        pub const IO: SIG = .POLL;
         pub const IOT: SIG = .ABRT;
 
         HUP = 1,
@@ -11267,15 +11268,22 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo;
 pub const taskid_t = illumos.taskid_t;
 pub const zoneid_t = illumos.zoneid_t;
 
+pub const B_ABSOLUTE_TIMEOUT = haiku.B_ABSOLUTE_TIMEOUT;
 pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH;
+pub const B_TIMEOUT_REAL_TIME_BASE = haiku.B_TIMEOUT_REAL_TIME_BASE;
 pub const DirEnt = haiku.DirEnt;
+pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc;
+pub const _kern_create_sem = haiku._kern_create_sem;
+pub const _kern_delete_sem = haiku._kern_delete_sem;
 pub const _kern_open_dir = haiku._kern_open_dir;
 pub const _kern_read_dir = haiku._kern_read_dir;
 pub const _kern_read_stat = haiku._kern_read_stat;
+pub const _kern_release_sem_etc = haiku._kern_release_sem_etc;
 pub const _kern_rewind_dir = haiku._kern_rewind_dir;
 pub const area_id = haiku.area_id;
 pub const find_thread = haiku.find_thread;
 pub const get_system_info = haiku.get_system_info;
+pub const on_exit_thread = haiku.on_exit_thread;
 pub const port_id = haiku.port_id;
 pub const readv_pos = haiku.readv_pos;
 pub const sem_id = haiku.sem_id;
diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig
index 768935574d2912e79ea21f5bf1b4cd1f6f80b800..dd8bb8abf621324ba3ff2c9765f17524e30624c6 100644
--- a/lib/std/c/haiku.zig
+++ b/lib/std/c/haiku.zig
@@ -11,12 +11,19 @@ comptime {
 }
 
 pub const B_OS_NAME_LENGTH = 32;
+pub const B_ABSOLUTE_TIMEOUT = 0x10;
+pub const B_TIMEOUT_REAL_TIME_BASE = 0x40;
 
+pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id;
+pub extern "root" fn _kern_delete_sem(id: sem_id) status_t;
+pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t;
+pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t;
 pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
 pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
 pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
 pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
 
+pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t;
 pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id;
 pub extern "root" fn get_system_info(info: *system_info) status_t;
 
-- 
2.54.0


From fae25d72a94f09500cd15c7ff09caf939e7af1ab Mon Sep 17 00:00:00 2001
From: Elaine Gibson 
Date: Mon, 3 Aug 2026 11:52:34 +0100
Subject: [PATCH 122/215] compiler: remove haiku from defaultSingleThreaded

---
 src/target.zig | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/target.zig b/src/target.zig
index c64fd988cf4de9c881a8e79041ea8f7b80b099d0..e2cbd3e1839dd77df3d6926ee7333dccf405558c 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -118,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {
         .wasm32, .wasm64 => return true,
         else => {},
     }
-    switch (target.os.tag) {
-        .haiku => return true,
-        else => {},
-    }
     return false;
 }
 
-- 
2.54.0


From 4b726207b8eb5a8a0605f3cc164ff0364733c31b Mon Sep 17 00:00:00 2001
From: gubbu 
Date: Mon, 3 Aug 2026 16:07:55 +0200
Subject: [PATCH 123/215] fix: NCCS wrong for std.os.linux struct termios/2

---
 lib/std/os/linux.zig | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 5a3a0ff263ea99affa6c102f15699ca7eb079898..8fd3fca48e788610aa574ced6d7c7c56a90c0568 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -8181,13 +8181,11 @@ pub const rusage = extern struct {
 
 pub const NCC = if (is_ppc) 10 else 8;
 pub const NCCS = if (is_mips)
-    32
-else if (is_ppc or native_arch == .alpha)
-    19
+    23
 else if (is_sparc)
     17
 else
-    32;
+    19;
 
 pub const speed_t = if (is_ppc) enum(c_uint) {
     B0 = 0x0000000,
-- 
2.54.0


From 97ced1272df0236a01a72deaaf55e895f2bf62b0 Mon Sep 17 00:00:00 2001
From: Jacob Young 
Date: Mon, 3 Aug 2026 20:53:56 -0400
Subject: [PATCH 124/215] std.math.float: evaluate some constants at comptime

QEMU can mistranslate this code, but since it can be evaluated at
comptime anyway, force comptime eval as both a workaround for the
mistranslation and because it is a desirable change anyway.
---
 lib/std/math/float.zig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/std/math/float.zig b/lib/std/math/float.zig
index 4bc67d494abac15c21e791f15fc56802e0fb87b8..e84bcdc4f295e1edad123673991df5b85f1cea4c 100644
--- a/lib/std/math/float.zig
+++ b/lib/std/math/float.zig
@@ -112,17 +112,17 @@ pub fn FloatRepr(comptime Float: type) type {
             /// This currently truncates denormal values, which needs to be fixed before this can be used to
             /// produce a rounded value.
             pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {
-                if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
+                if (normalized.exponent > comptime BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
                     .mantissa = 0,
                     .exponent = .infinite,
                     .sign = sign,
                 });
                 const mantissa = @as(Mantissa, 1 << fractional_bits) | normalized.fraction;
-                if (normalized.exponent < BiasedExponent.min_normal.unbias()) return @bitCast(Repr{
+                if (normalized.exponent < comptime BiasedExponent.min_normal.unbias()) return @bitCast(Repr{
                     .mantissa = @truncate(std.math.shr(
                         Mantissa,
                         mantissa,
-                        BiasedExponent.min_normal.unbias() - normalized.exponent,
+                        (comptime BiasedExponent.min_normal.unbias()) - normalized.exponent,
                     )),
                     .exponent = .denormal,
                     .sign = sign,
-- 
2.54.0


From 2d100ec764cdf3a99f02c6273bd6aab2ca78f2f8 Mon Sep 17 00:00:00 2001
From: jpk68 
Date: Sat, 20 Jun 2026 14:56:13 -0400
Subject: [PATCH 125/215] std.hash: fix inconsistent spacing

---
 lib/std/hash/cityhash.zig | 2 +-
 lib/std/hash/xxhash.zig   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/hash/cityhash.zig b/lib/std/hash/cityhash.zig
index 781949321d0c37d624b29f8f5599fff5f0873f39..1acb039dab5551e4e0ef0b691c4d5ae8770bebb7 100644
--- a/lib/std/hash/cityhash.zig
+++ b/lib/std/hash/cityhash.zig
@@ -16,7 +16,7 @@ fn fetch64(ptr: [*]const u8, offset: usize) u64 {
 pub const CityHash32 = struct {
     const Self = @This();
 
-    // Magic numbers for 32-bit hashing.  Copied from Murmur3.
+    // Magic numbers for 32-bit hashing. Copied from Murmur3.
     const c1: u32 = 0xcc9e2d51;
     const c2: u32 = 0x1b873593;
 
diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig
index 72c8bff280548134abcb34a71857c7c101683dae..b33ac61b5bd233a0c6ccea59033d7ee6c2b62045 100644
--- a/lib/std/hash/xxhash.zig
+++ b/lib/std/hash/xxhash.zig
@@ -760,7 +760,7 @@ pub const XxHash3 = struct {
         var accumulator_copy = self.accumulator;
         var last_block_copy: [block_bytes]u8 = undefined;
 
-        // Digest the last block onthe Accumulator copy.
+        // Digest the last block on the Accumulator copy.
         return accumulator_copy.digest(self.total_len, last_block: {
             if (self.buffered >= block_bytes) {
                 const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;
-- 
2.54.0


From 988613be67133ce6f2de3ac8b3f2e63f610c4470 Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 6 Jul 2026 19:29:17 +0200
Subject: [PATCH 126/215] std.Build.Configuration: improve storage of preopens
 in run steps

---
 lib/compiler/Maker/Step/Run.zig | 14 +++++++-------
 lib/std/Build/Configuration.zig | 11 ++++++++---
 lib/std/Build/Serialize.zig     | 11 +++++++++--
 lib/std/Build/Step/Run.zig      |  5 +++--
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig
index b6fc911f01f8d25a27cf2f3829118accfe2f58ea..0ac652096de65af81a50d25fb94532c805d0205c 100644
--- a/lib/compiler/Maker/Step/Run.zig
+++ b/lib/compiler/Maker/Step/Run.zig
@@ -64,9 +64,9 @@ pub fn make(
         }
     }
 
-    for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, path| {
-        man.hash.addBytesZ(name.slice(conf));
-        const cwd_path = try maker.resolveLazyPathIndex(arena, path, run_index);
+    for (conf_run.preopens.slice) |preopen| {
+        man.hash.addBytesZ(preopen.name.slice(conf));
+        const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index);
         man.hash.addBytes(try cwd_path.toString(arena));
     }
 
@@ -1917,14 +1917,14 @@ fn runCommand(
                     },
                     .wasmtime => |bin_name| {
                         if (graph.enable_wasmtime) {
-                            try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len + conf_run.preopen_names.slice.len);
+                            try interp_argv.ensureUnusedCapacity(arena, 3 + argv.len + conf_run.preopens.slice.len);
                             interp_argv.appendAssumeCapacity(bin_name);
                             interp_argv.appendAssumeCapacity("--dir=.");
-                            for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, lazy_path| {
-                                const path = try maker.resolveLazyPath(arena, lazy_path.get(conf), run_index);
+                            for (conf_run.preopens.slice) |preopen| {
+                                const path = try maker.resolveLazyPath(arena, preopen.path.get(conf), run_index);
                                 path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e|
                                     return step.fail(maker, "failed creating directory {f}: {t}", .{ path, e });
-                                interp_argv.appendAssumeCapacity(try arena.print("--dir={f}::{s}", .{ path, name.slice(conf) }));
+                                interp_argv.appendAssumeCapacity(try arena.print("--dir={f}::{s}", .{ path, preopen.name.slice(conf) }));
                             }
                             // Wasmtime doeesn't inherit environment variables from the parent process
                             // by default. '-S inherit-env' was added in Wasmtime version 20.
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index b04a7c592460b1db60c80b412edcbf973c5d29e2..ccdb74499c7b41ed30b6f8b62953710e207d459b 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -569,8 +569,7 @@ pub const Step = extern struct {
         flags2: Flags2,
         args: Storage.LengthPrefixedList(Arg.Index),
         cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index),
-        preopen_names: Storage.LengthPrefixedList(String),
-        preopen_paths: Storage.LengthPrefixedList(LazyPath.Index),
+        preopens: Storage.FlagLengthPrefixedList(.flags, .preopens, Preopen),
         captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream),
         captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream),
         file_inputs: Storage.LengthPrefixedList(LazyPath.Index),
@@ -646,6 +645,11 @@ pub const Step = extern struct {
             manual,
         };
 
+        pub const Preopen = extern struct {
+            name: String,
+            path: LazyPath.Index,
+        };
+
         pub const StdIn = union(@This().Tag) {
             none: void,
             bytes: Bytes,
@@ -676,7 +680,8 @@ pub const Step = extern struct {
             captured_stdout: bool,
             captured_stderr: bool,
             environ_map: bool,
-            _: u4 = 0,
+            preopens: bool,
+            _: u3 = 0,
         };
 
         pub const Flags2 = packed struct(u32) {
diff --git a/lib/std/Build/Serialize.zig b/lib/std/Build/Serialize.zig
index 8849f7aaeec31bf6093f3ee60ec48ba2376f026d..72355264d978c15b712d92242df14f0c92eb4b6f 100644
--- a/lib/std/Build/Serialize.zig
+++ b/lib/std/Build/Serialize.zig
@@ -454,6 +454,13 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
                             },
                             else => {},
                         }
+                        const preopens = try arena.alloc(
+                            Configuration.Step.Run.Preopen,
+                            run.preopens.count(),
+                        );
+                        for (preopens, run.preopens.keys(), run.preopens.values()) |*dest, name, path| {
+                            dest.* = .{ .name = name, .path = try s.addLazyPath(path) };
+                        }
 
                         break :e try wc.addExtraErased(Configuration.Step.Run, .{
                             .flags = .{
@@ -482,6 +489,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
                                 .captured_stdout = run.captured_stdout != null,
                                 .captured_stderr = run.captured_stderr != null,
                                 .environ_map = run.environ_map != null,
+                                .preopens = run.preopens.count() > 0,
                             },
                             .flags2 = .{
                                 .expect_stderr_exact = expect_stderr_exact != null,
@@ -496,8 +504,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
                             .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) },
                             .args = .{ .slice = try s.initArgsList(run.argv.items) },
                             .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) },
-                            .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) },
-                            .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) },
+                            .preopens = .{ .slice = preopens },
                             .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{
                                 .basename = try wc.addString(cs.basename),
                                 .generated_file = cs.generated_file,
diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig
index a0fc19f5dc8dc33d5f2ee870bd6210c0172d1bd4..9e1f3ca7047585a13fcae9b77de0afb6c45f9eee 100644
--- a/lib/std/Build/Step/Run.zig
+++ b/lib/std/Build/Step/Run.zig
@@ -28,7 +28,7 @@ environ_map: ?*EnvMap,
 
 /// Named files that will be provided to the parent process.
 /// See `std.process.Preopens`.
-preopens: std.array_hash_map.String(Build.LazyPath),
+preopens: std.array_hash_map.Auto(Configuration.String, Build.LazyPath),
 
 /// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables.
 color: Color = .auto,
@@ -624,11 +624,12 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {
 
 pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void {
     const graph = run.step.owner.graph;
+    const wc = &graph.wip_configuration;
     const arena = graph.arena;
     resource.addStepDependencies(&run.step);
     run.preopens.put(
         arena,
-        graph.dupeString(name),
+        wc.addString(name) catch @panic("OOM"),
         resource.dupe(graph),
     ) catch @panic("OOM");
 }
-- 
2.54.0


From f0354179a88d9c8274e571dc1e62a29e9c58376b Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 4 Aug 2026 10:54:14 -0700
Subject: [PATCH 127/215] fetch: remove --global-cache-dir argument

This must be set with an env var now, just like `zig build` because by
the time we make it to the child process it is too late, the global
cache directory has already been observed.

closes #36144
---
 lib/compiler/Maker.zig | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index ade19eeb33a672846fb80709ff26089cbb883fac..2339de5ff1e3612029d7be22480e212e0592f998 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -1439,7 +1439,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
 
     const color: Color = Color.settingFromEnvironment(environ_map);
     var opt_path_or_url: ?[]const u8 = null;
-    var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
     var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);
     var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);
     var debug_hash: bool = false;
@@ -1455,8 +1454,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
             if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
                 try Io.File.stdout().writeStreamingAll(io, usage_fetch);
                 return process.cleanExit(io);
-            } else if (mem.eql(u8, arg, "--global-cache-dir")) {
-                override_global_cache_dir = nextArgOrFatal(args, &arg_i);
             } else if (mem.eql(u8, arg, "--cache-dir")) {
                 override_local_cache_dir = nextArgOrFatal(args, &arg_i);
             } else if (mem.eql(u8, arg, "--pkg-dir")) {
@@ -1736,7 +1733,6 @@ const usage_fetch =
     \\
     \\Options:
     \\  -h, --help                    Print this help and exit
-    \\  --global-cache-dir [path]     Override path to global Zig cache directory
     \\  --cache-dir [path]            Override path to local cache directory
     \\  --pkg-dir [path]              Override path to local package directory
     \\  --debug-hash                  Print verbose hash information to stdout
-- 
2.54.0


From bddd915dd92abbf106a9dc5600782c3fd61b0a37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Tue, 4 Aug 2026 20:40:01 +0200
Subject: [PATCH 128/215] zig cc: fix CPU model and features not being passed
 to the assembler

---
 src/Compilation.zig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/Compilation.zig b/src/Compilation.zig
index 0952e9f7dc05456c4a8d4e6cbc35fa17d14ef484..56a245a1e0769f915aa25c6d7daeb3d0d10716de 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -6663,6 +6663,8 @@ pub fn addCCArgs(
 
     // Only compiled files support these flags.
     switch (ext) {
+        .assembly,
+        .assembly_with_cpp,
         .c,
         .h,
         .cpp,
-- 
2.54.0


From 142bd772e11697e296dcd9cda379db90b48b60a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Tue, 4 Aug 2026 20:23:17 +0200
Subject: [PATCH 129/215] test: add loongarch32-linux-gnu[sf] to module test
 matrix

---
 test/tests.zig | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/test/tests.zig b/test/tests.zig
index 90442edf52c9135eaf901c075828191cae6e45f3..8cd22d3b8fff0b09d9a9ac96dc8fe02184df5eab 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -455,6 +455,23 @@ const module_test_targets = blk: {
                 .abi = .none,
             },
         },
+        .{
+            .target = .{
+                .cpu_arch = .loongarch32,
+                .os_tag = .linux,
+                .abi = .gnu,
+            },
+            .link_libc = true,
+        },
+        .{
+            .target = .{
+                .cpu_arch = .loongarch32,
+                .os_tag = .linux,
+                .abi = .gnusf,
+            },
+            .link_libc = true,
+            .extra_target = true,
+        },
 
         .{
             .target = .{
-- 
2.54.0


From 8cb4459f36704a3660dcbce30e80f6e01a66b39e Mon Sep 17 00:00:00 2001
From: c-kappel 
Date: Tue, 4 Aug 2026 22:15:44 +0200
Subject: [PATCH 130/215] Sema: correctly check `packed_offset` when coercing
 to c pointer (#36097)

Co-authored-by: c-kappel 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36097
Reviewed-by: Justus Klausecker 
---
 src/Sema.zig                                  | 26 +++++++++----------
 .../coercion_from_vector_element_to_c_ptr.zig | 11 ++++++++
 2 files changed, 24 insertions(+), 13 deletions(-)
 create mode 100644 test/cases/compile_errors/coercion_from_vector_element_to_c_ptr.zig

diff --git a/src/Sema.zig b/src/Sema.zig
index 797bc299c34d8831c6a287106c35878a1d8f8152..1b81e7653ea9d8586e8c887978078c9a97ba6925 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -30223,6 +30223,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
         } };
         return false;
     }
+
+    if (inst_info.packed_offset.host_size != dest_info.packed_offset.host_size or
+        inst_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset)
+    {
+        in_memory_result.* = .{ .ptr_bit_range = .{
+            .actual_host = inst_info.packed_offset.host_size,
+            .wanted_host = dest_info.packed_offset.host_size,
+            .actual_offset = inst_info.packed_offset.bit_offset,
+            .wanted_offset = dest_info.packed_offset.bit_offset,
+        } };
+        return false;
+    }
+
     if (inst_info.flags.alignment == .none and dest_info.flags.alignment == .none) return true;
     if (len0) return true;
 
@@ -30243,19 +30256,6 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
         } };
         return false;
     }
-
-    if (inst_info.packed_offset.host_size != dest_info.packed_offset.host_size or
-        inst_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset)
-    {
-        in_memory_result.* = .{ .ptr_bit_range = .{
-            .actual_host = inst_info.packed_offset.host_size,
-            .wanted_host = dest_info.packed_offset.host_size,
-            .actual_offset = inst_info.packed_offset.bit_offset,
-            .wanted_offset = dest_info.packed_offset.bit_offset,
-        } };
-        return false;
-    }
-
     return true;
 }
 
diff --git a/test/cases/compile_errors/coercion_from_vector_element_to_c_ptr.zig b/test/cases/compile_errors/coercion_from_vector_element_to_c_ptr.zig
new file mode 100644
index 0000000000000000000000000000000000000000..8bf69016a6a8e0c7e51ef50f84dd632f9232037e
--- /dev/null
+++ b/test/cases/compile_errors/coercion_from_vector_element_to_c_ptr.zig
@@ -0,0 +1,11 @@
+export fn foo() void {
+    var size: @Vector(4, c_int) = undefined;
+    bar(&size[0]);
+}
+extern fn bar([*c]c_int) void;
+
+// error
+//
+// 3:9: error: expected type '[*c]c_int', found '*align(4:0:4:0) c_int'
+// 3:9: note: pointer host size '4' cannot cast into pointer host size '0'
+// 5:15: note: parameter type declared here
-- 
2.54.0


From 5f74e4f3f8b909835ef794253a98a77868b3880e Mon Sep 17 00:00:00 2001
From: Matthew Lugg 
Date: Tue, 21 Jul 2026 11:02:29 +0100
Subject: [PATCH 131/215] Sema: make loading uninstantiable types a runtime
 safety panic

For generic code, it is far more useful to consider this equivalent to
`unreachable`. Meanwhile, it is difficult to accidentally write concrete
code which performs this operation, so very little is actually lost from
not having a compile error.

If we accept that this operation does not trigger a compile error, then
it already has the potential to invoke Illegal Behavior today, because
uninstantiable types have an unspecified size in memory, so the
dereference always potentially exceeds the pointer's provenance. (That
said, this only means it is *possible* for the operation to invoke IB,
so the langspec should nonetheless explicitly specify that dereferencing
a pointer to an uninstantiable type is itself Illegal Behavior.)

Storing uninstantiable types into memory does not require any specific
language rules, because that operation can never be reached anyway due
to it requiring an operand (the RHS of `a = b`) whose type is the store
type, which is (by definition) impossible for uninstantiable types.

Resolves: https://codeberg.org/ziglang/zig/issues/36247
---
 lib/std/debug.zig                             |  4 ++
 lib/std/debug/no_panic.zig                    |  5 ++
 lib/std/debug/simple_panic.zig                |  4 ++
 src/Sema.zig                                  | 63 ++++++++++++++++++-
 src/Zcu.zig                                   |  4 ++
 .../compile_errors/initialize_empty_union.zig | 31 ---------
 .../cases/safety/load_uninstantiable_enum.zig | 20 ++++++
 .../load_uninstantiable_enum_from_slice.zig   | 21 +++++++
 .../safety/load_uninstantiable_union.zig      | 23 +++++++
 .../load_uninstantiable_union_from_slice.zig  | 24 +++++++
 .../incremental/change_panic_handler_explicit |  3 +
 11 files changed, 169 insertions(+), 33 deletions(-)
 create mode 100644 test/cases/safety/load_uninstantiable_enum.zig
 create mode 100644 test/cases/safety/load_uninstantiable_enum_from_slice.zig
 create mode 100644 test/cases/safety/load_uninstantiable_union.zig
 create mode 100644 test/cases/safety/load_uninstantiable_union_from_slice.zig

diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 898ae314d9084e35fed670b03854959ec06beead..faeed5f667c9a8dc4ec0f38ef2a829b5f42dff3c 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -207,6 +207,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
             @branchHint(.cold);
             call("'noreturn' function returned", @returnAddress());
         }
+        pub fn loadUninstantiableType() noreturn {
+            @branchHint(.cold);
+            call("attempt to load uninstantiable type", @returnAddress());
+        }
     };
 }
 
diff --git a/lib/std/debug/no_panic.zig b/lib/std/debug/no_panic.zig
index f24317b9b7d66ae9076df3d4790cfa88d47e1a26..d47c9799a990e0d53cdf61e735b008deb355fd44 100644
--- a/lib/std/debug/no_panic.zig
+++ b/lib/std/debug/no_panic.zig
@@ -134,3 +134,8 @@ pub fn noreturnReturned() noreturn {
     @branchHint(.cold);
     @trap();
 }
+
+pub fn loadUninstantiableType() noreturn {
+    @branchHint(.cold);
+    @trap();
+}
diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig
index a5a09fa1162e75cf9aad5a69a1bfcd3a3e1845d9..af7231251aa0e9bd94ef1eef36280d110b4d2019 100644
--- a/lib/std/debug/simple_panic.zig
+++ b/lib/std/debug/simple_panic.zig
@@ -126,3 +126,7 @@ pub fn memcpyAlias() noreturn {
 pub fn noreturnReturned() noreturn {
     call("'noreturn' function returned", null);
 }
+
+pub fn loadUninstantiableType() noreturn {
+    call("attempt to load uninstantiable type", null);
+}
diff --git a/src/Sema.zig b/src/Sema.zig
index 1b81e7653ea9d8586e8c887978078c9a97ba6925..96bb93f02bcd78185e14c04f40ab832fc09868b4 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -31040,7 +31040,18 @@ fn analyzeLoad(
     const comptime_only = switch (elem_ty.classify(zcu)) {
         .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) {
             .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}),
-            else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)}),
+            else => {
+                // Loading an uninstantiable type always invokes Illegal Behavior.
+                if (block.isComptime()) {
+                    return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)});
+                } else if (block.wantSafety()) {
+                    try sema.safetyPanic(block, src, .load_uninstantiable_type);
+                    return .unreachable_value;
+                } else {
+                    _ = try block.addNoOp(.unreach);
+                    return .unreachable_value;
+                }
+            },
         },
         .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?),
         .runtime => false,
@@ -35059,12 +35070,60 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
         .@"panic.copyLenMismatch",
         .@"panic.memcpyAlias",
         .@"panic.noreturnReturned",
+        .@"panic.loadUninstantiableType",
         => try pt.funcType(.{
             .param_types = &.{},
             .return_type = .noreturn_type,
         }),
 
-        else => unreachable,
+        .StackTrace,
+        .CallingConvention,
+        .SourceLocation,
+        .Signedness,
+        .AddressSpace,
+        .VaList,
+        .CallModifier,
+        .AtomicOrder,
+        .AtomicRmwOp,
+        .ReduceOp,
+        .FloatMode,
+        .PrefetchOptions,
+        .ExportOptions,
+        .ExternOptions,
+        .BranchHint,
+        .assembly,
+        .@"assembly.Clobbers",
+        .Type,
+        .@"Type.Fn",
+        .@"Type.Fn.ParamAttributes",
+        .@"Type.Fn.Attributes",
+        .@"Type.Int",
+        .@"Type.Float",
+        .@"Type.Pointer",
+        .@"Type.Pointer.Size",
+        .@"Type.Pointer.Attributes",
+        .@"Type.Array",
+        .@"Type.Vector",
+        .@"Type.Optional",
+        .@"Type.ErrorUnion",
+        .@"Type.ErrorSet",
+        .@"Type.Enum",
+        .@"Type.Enum.Mode",
+        .@"Type.Union",
+        .@"Type.Union.FieldAttributes",
+        .@"Type.Struct",
+        .@"Type.Struct.FieldAttributes",
+        .@"Type.ContainerLayout",
+        .@"Type.Opaque",
+        .@"Type.Spirv",
+        .@"Type.Spirv.Image",
+        .@"Type.Spirv.Image.Usage",
+        .@"Type.Spirv.Image.Format",
+        .@"Type.Spirv.Image.Dimensionality",
+        .@"Type.Spirv.Image.Depth",
+        .@"Type.Spirv.Image.Access",
+        .panic,
+        => unreachable, // not a function (`decl.kind() != .func`)
     };
 }
 
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 465506eb7b41dcbcb16620c7ef84dc8b5f406ea4..0c231862cb0720fec4419115e08b712eacbdcf6f 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -517,6 +517,7 @@ pub const StdLangDecl = enum {
     @"panic.copyLenMismatch",
     @"panic.memcpyAlias",
     @"panic.noreturnReturned",
+    @"panic.loadUninstantiableType",
 
     VaList,
 
@@ -606,6 +607,7 @@ pub const StdLangDecl = enum {
             .@"panic.copyLenMismatch",
             .@"panic.memcpyAlias",
             .@"panic.noreturnReturned",
+            .@"panic.loadUninstantiableType",
             => .func,
         };
     }
@@ -679,6 +681,7 @@ pub const SimplePanicId = enum {
     copy_len_mismatch,
     memcpy_alias,
     noreturn_returned,
+    load_uninstantiable_type,
 
     pub fn toStdLangDecl(id: SimplePanicId) StdLangDecl {
         return switch (id) {
@@ -702,6 +705,7 @@ pub const SimplePanicId = enum {
             .copy_len_mismatch          => .@"panic.copyLenMismatch",
             .memcpy_alias               => .@"panic.memcpyAlias",
             .noreturn_returned          => .@"panic.noreturnReturned",
+            .load_uninstantiable_type   => .@"panic.loadUninstantiableType",
             // zig fmt: on
         };
     }
diff --git a/test/cases/compile_errors/initialize_empty_union.zig b/test/cases/compile_errors/initialize_empty_union.zig
index a7945a105b6d973411f6d2e31810ae6e5f7e595e..fe8203c1ed1873c2c4634eae13ab177ea079474d 100644
--- a/test/cases/compile_errors/initialize_empty_union.zig
+++ b/test/cases/compile_errors/initialize_empty_union.zig
@@ -28,25 +28,6 @@ export fn init5() void {
     _ = @as(U5, undefined);
 }
 
-export fn deref0(ptr: *const U0) void {
-    _ = ptr.*;
-}
-export fn deref1(ptr: *const U1) void {
-    _ = ptr.*;
-}
-export fn deref2(ptr: *const U2) void {
-    _ = ptr.*;
-}
-export fn deref3(ptr: *const U3) void {
-    _ = ptr.*;
-}
-export fn deref4(ptr: *const U4) void {
-    _ = ptr.*;
-}
-export fn deref5(ptr: *const U5) void {
-    _ = ptr.*;
-}
-
 // error
 //
 // :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)'
@@ -67,15 +48,3 @@ export fn deref5(ptr: *const U5) void {
 // :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)'
 // :28:17: note: cannot coerce to uninstantiable type 'tmp.U5'
 // :10:12: note: union declared here
-// :32:12: error: cannot load uninstantiable type 'tmp.U0'
-// :5:12: note: union declared here
-// :35:12: error: cannot load uninstantiable type 'tmp.U1'
-// :6:12: note: union declared here
-// :38:12: error: cannot load uninstantiable type 'tmp.U2'
-// :7:12: note: union declared here
-// :41:12: error: cannot load uninstantiable type 'tmp.U3'
-// :8:12: note: union declared here
-// :44:12: error: cannot load uninstantiable type 'tmp.U4'
-// :9:12: note: union declared here
-// :47:12: error: cannot load uninstantiable type 'tmp.U5'
-// :10:12: note: union declared here
diff --git a/test/cases/safety/load_uninstantiable_enum.zig b/test/cases/safety/load_uninstantiable_enum.zig
new file mode 100644
index 0000000000000000000000000000000000000000..91a26417b689a0f06ae1ed1462bffdab5366cd30
--- /dev/null
+++ b/test/cases/safety/load_uninstantiable_enum.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const E = enum {};
+pub fn main() error{TestFailed}!void {
+    const bytes: [32]u8 = @splat(0);
+    const ptr: *const E = @ptrCast(&bytes);
+    _ = ptr.*;
+    return error.TestFailed;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux,wasm32-wasi
diff --git a/test/cases/safety/load_uninstantiable_enum_from_slice.zig b/test/cases/safety/load_uninstantiable_enum_from_slice.zig
new file mode 100644
index 0000000000000000000000000000000000000000..57c308f8f6b15ca4f61eb36a3da0c246b6831dd8
--- /dev/null
+++ b/test/cases/safety/load_uninstantiable_enum_from_slice.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const E = enum {};
+pub fn main() error{TestFailed}!void {
+    const bytes: [32]u8 = @splat(0);
+    const ptr: *const [1]E = @ptrCast(&bytes);
+    const slice: []const E = ptr;
+    _ = slice[0];
+    return error.TestFailed;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux,wasm32-wasi
diff --git a/test/cases/safety/load_uninstantiable_union.zig b/test/cases/safety/load_uninstantiable_union.zig
new file mode 100644
index 0000000000000000000000000000000000000000..87f84e07c7f624104d797b94037fc6148491265b
--- /dev/null
+++ b/test/cases/safety/load_uninstantiable_union.zig
@@ -0,0 +1,23 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const U = union {
+    foo: struct { a: u8, b: noreturn, },
+    bar: enum {},
+};
+pub fn main() error{TestFailed}!void {
+    const bytes: [32]u8 = @splat(0);
+    const ptr: *const U = @ptrCast(&bytes);
+    _ = ptr.*;
+    return error.TestFailed;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux,wasm32-wasi
diff --git a/test/cases/safety/load_uninstantiable_union_from_slice.zig b/test/cases/safety/load_uninstantiable_union_from_slice.zig
new file mode 100644
index 0000000000000000000000000000000000000000..844bfd0b7d766bfb9e5eb0f911061eda7bace0d6
--- /dev/null
+++ b/test/cases/safety/load_uninstantiable_union_from_slice.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to load uninstantiable type")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const U = union {
+    foo: struct { a: u8, b: noreturn, },
+    bar: enum {},
+};
+pub fn main() error{TestFailed}!void {
+    const bytes: [32]u8 = @splat(0);
+    const ptr: *const [1]U = @ptrCast(&bytes);
+    const slice: []const U = ptr;
+    _ = slice[0];
+    return error.TestFailed;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux,wasm32-wasi
diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit
index 662d13847f9800553b41fca4e9545e3bc07dbb17..f748a57afc43e7d18e5458549a18c173d21dc56c 100644
--- a/test/incremental/change_panic_handler_explicit
+++ b/test/incremental/change_panic_handler_explicit
@@ -36,6 +36,7 @@ pub const panic = struct {
     pub const copyLenMismatch = no_panic.copyLenMismatch;
     pub const memcpyAlias = no_panic.memcpyAlias;
     pub const noreturnReturned = no_panic.noreturnReturned;
+    pub const loadUninstantiableType = no_panic.loadUninstantiableType;
 };
 fn myPanic(msg: []const u8, _: ?usize) noreturn {
     var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
@@ -84,6 +85,7 @@ pub const panic = struct {
     pub const copyLenMismatch = no_panic.copyLenMismatch;
     pub const memcpyAlias = no_panic.memcpyAlias;
     pub const noreturnReturned = no_panic.noreturnReturned;
+    pub const loadUninstantiableType = no_panic.loadUninstantiableType;
 };
 fn myPanic(msg: []const u8, _: ?usize) noreturn {
     var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
@@ -132,6 +134,7 @@ pub const panic = struct {
     pub const copyLenMismatch = no_panic.copyLenMismatch;
     pub const memcpyAlias = no_panic.memcpyAlias;
     pub const noreturnReturned = no_panic.noreturnReturned;
+    pub const loadUninstantiableType = no_panic.loadUninstantiableType;
 };
 fn myPanicNew(msg: []const u8, _: ?usize) noreturn {
     var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
-- 
2.54.0


From 0be5e81cc8cae524768e6a66e0af84c4d2b28314 Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Sat, 1 Aug 2026 22:50:11 +0200
Subject: [PATCH 132/215] Maker: fix `confPathDepToCachePath` on non-root build
 root

---
 lib/compiler/Maker.zig | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index e33605d5dc9a3dac4359f5413a24c3feba7de76a..6cbe61a1b3509d633c48e083cdc6fdf853d306c9 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -1451,7 +1451,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
         if (config_man) |man| for (configuration.path_deps) |path_dep| {
             switch (path_dep.flags.mode) {
                 .directory => {}, // TODO
-                .contents => try man.addPathPost(confPathDepToCachePath(graph, &configuration, path_dep)),
+                .contents => try man.addPathPost(try confPathDepToCachePath(arena, graph, &configuration, path_dep)),
                 .metadata => {}, // TODO
             }
         };
@@ -3917,7 +3917,12 @@ const Templates = struct {
     }
 };
 
-fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep: Configuration.PathDep) Path {
+fn confPathDepToCachePath(
+    arena: Allocator,
+    graph: *const Graph,
+    c: *const Configuration,
+    path_dep: Configuration.PathDep,
+) Allocator.Error!Path {
     const sub_path = path_dep.sub.slice(c);
     return switch (path_dep.flags.base) {
         .cwd => .{
@@ -3933,11 +3938,11 @@ fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep
             .sub_path = sub_path,
         },
         .build_root => .{
-            .root_dir = switch (path_dep.pkg.unwrap().?) {
-                .root => graph.build_root_directory,
-                _ => @panic("TODO"),
+            .root_dir = graph.build_root_directory,
+            .sub_path = switch (path_dep.pkg.unwrap().?) {
+                .root => sub_path,
+                else => |index| try Dir.path.join(arena, &.{ index.get(c).?.root_path.slice(c), sub_path }),
             },
-            .sub_path = sub_path,
         },
         .zig_lib => .{
             .root_dir = graph.zig_lib_directory,
-- 
2.54.0


From 5b18caf2603066e5d29fc6f6b1fac931d85d1010 Mon Sep 17 00:00:00 2001
From: rpkak 
Date: Sun, 5 Jul 2026 10:22:21 +0200
Subject: [PATCH 133/215] Maker: remove '--global-cache-dir' from 'zig build
 --help'

this option does not exist anymore
---
 lib/compiler/Maker/ScannedConfig.zig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig
index ead8acf064021af8ad3f4a344657189f4977fb14..2efe328ba95b95ae14ff924b23e2d36d40c08bd2 100644
--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -341,7 +341,6 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
         \\  --error-limit [num]          Set the maximum amount of distinct error values
         \\  --build-file [file]          Override path to build.zig
         \\  --cache-dir [path]           Override path to local Zig cache directory
-        \\  --global-cache-dir [path]    Override path to global Zig cache directory
         \\  --zig-lib=[arg]              Override path to Zig lib directory
         \\  --seed [integer]             For shuffling dependency traversal order (default: random)
         \\  --cache-poison[=mode]        Override configuration caching behavior
-- 
2.54.0


From 9243d1d975c93f68c9c73a6d7a235784e04b3087 Mon Sep 17 00:00:00 2001
From: taoqy <845767657@qq.com>
Date: Mon, 8 Jun 2026 17:23:06 +0800
Subject: [PATCH 134/215] zig build: update print-configuration

---
 lib/compiler/Maker/ScannedConfig.zig | 46 +++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig
index 2efe328ba95b95ae14ff924b23e2d36d40c08bd2..cc8c27a35b78b745c4a4606c1a386ee576feffa5 100644
--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -12,10 +12,6 @@ top_level_steps: std.array_hash_map.String(Configuration.Step.Index),
 path: std.Build.Cache.Path,
 
 pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
-    std.log.err("TODO also print paths", .{});
-    std.log.err("TODO also print unlazy deps", .{});
-    std.log.err("TODO also print system integrations", .{});
-    std.log.err("TODO also print available options", .{});
     const c = &sc.configuration;
     var serializer: Serializer = .{ .writer = w };
     var s = try serializer.beginStruct(.{});
@@ -45,6 +41,48 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
         try tf.end();
     }
 
+    {
+        var tf = try s.beginTupleField("path_deps", .{});
+        for (c.path_deps_base, c.path_deps_sub) |base, sub| {
+            var sf = try tf.beginStructField(.{});
+            try sf.field("base", @tagName(base), .{});
+            try sf.field("sub", sub.slice(c), .{});
+            try sf.end();
+        }
+        try tf.end();
+    }
+
+    {
+        var tf = try s.beginTupleField("unlazy_deps", .{});
+        for (c.unlazy_deps) |dep| {
+            try tf.field(dep.slice(c), .{});
+        }
+        try tf.end();
+    }
+
+    {
+        var tf = try s.beginTupleField("system_integrations", .{});
+        for (c.system_integrations) |opt| {
+            var sf = try tf.beginStructField(.{});
+            try sf.field("name", opt.name.slice(c), .{});
+            try sf.field("status", opt.status, .{});
+            try sf.end();
+        }
+        try tf.end();
+    }
+
+    {
+        var tf = try s.beginTupleField("available_options", .{});
+        for (c.available_options) |opt| {
+            var sf = try tf.beginStructField(.{});
+            try sf.field("name", opt.name.slice(c), .{});
+            try sf.field("description", opt.description.slice(c), .{});
+            try sf.field("type", @tagName(opt.type), .{});
+            try sf.end();
+        }
+        try tf.end();
+    }
+
     try s.end();
 }
 
-- 
2.54.0


From 78f3aa0b179091fd72f0a2627aea92fd75b5f649 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Tue, 2 Jun 2026 14:58:52 +0200
Subject: [PATCH 135/215] compiler: mark redundant decls in @import("builtin")
 deprecated

ref https://github.com/ziglang/zig/issues/22267
---
 src/Builtin.zig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/Builtin.zig b/src/Builtin.zig
index e70252e47d8427eecac589c9d5711d9286d6b878..218a1f44875185ed67fa046976f9481fc811cfed 100644
--- a/src/Builtin.zig
+++ b/src/Builtin.zig
@@ -64,7 +64,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
         \\pub const unwind_tables: std.lang.UnwindTables = .{f};
         \\pub const is_test = {};
         \\pub const single_threaded = {};
+        \\/// Deprecated; to be removed in 0.18.0. Use `target.abi` instead.
         \\pub const abi: std.Target.Abi = .{f};
+        \\/// Deprecated; to be removed in 0.18.0. Use `target.cpu` instead.
         \\pub const cpu: std.Target.Cpu = .{{
         \\    .arch = .{f},
         \\    .model = &std.Target.{f}.cpu.{f},
@@ -95,6 +97,7 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
     try buffer.print(
         \\    }}),
         \\}};
+        \\/// Deprecated; to be removed in 0.18.0. Use `target.os` instead.
         \\pub const os: std.Target.Os = .{{
         \\    .tag = .{f},
         \\    .version_range = .{{
@@ -238,6 +241,7 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro
     const link_libc = opts.link_libc;
 
     try buffer.print(
+        \\/// Deprecated; to be removed in 0.18.0. Use `target.ofmt` instead.
         \\pub const object_format: std.Target.ObjectFormat = .{f};
         \\/// Deprecated, to be removed after 0.18.0
         \\pub const mode = optimize;
-- 
2.54.0


From ab14beeaadc4bae0dfcad1bf798f6f2bc4bb8aaf Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 4 Aug 2026 17:00:10 -0700
Subject: [PATCH 136/215] Maker.ScannedConfig: update for changed Configuration
 types

fixes invisible merge conflict from 9243d1d975c93f68c9c73a6d7a235784e04b3087
---
 lib/compiler/Maker/ScannedConfig.zig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig
index cc8c27a35b78b745c4a4606c1a386ee576feffa5..ed5661851351afb4c9a57b8723e2f4d13cd895ba 100644
--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -43,10 +43,10 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
 
     {
         var tf = try s.beginTupleField("path_deps", .{});
-        for (c.path_deps_base, c.path_deps_sub) |base, sub| {
+        for (c.path_deps) |path_dep| {
             var sf = try tf.beginStructField(.{});
-            try sf.field("base", @tagName(base), .{});
-            try sf.field("sub", sub.slice(c), .{});
+            try sf.field("base", @tagName(path_dep.flags.base), .{});
+            try sf.field("sub", path_dep.sub.slice(c), .{});
             try sf.end();
         }
         try tf.end();
-- 
2.54.0


From 9688e6e6208910b3e8dce5a6b93ea743fd46a575 Mon Sep 17 00:00:00 2001
From: Eric Joldasov 
Date: Tue, 16 Jun 2026 19:33:01 +0500
Subject: [PATCH 137/215] Resolve relative install directories against install
 prefix

This fixes a regression introduced on the master branch in commit
0505318efe0d2757a344dded9ae1607f948f7511
(PR https://codeberg.org/ziglang/zig/pulls/35428).

In Zig 0.16 and earlier, overriding install sub-directories (such as
`--prefix-lib-dir`) with a relative path correctly resolved them
against the "install prefix". The mentioned PR changed this behavior
(though this was not mentioned in its description), causing relative
path overrides to resolve against the "current working directory"
instead.

This commit restores the old behavior and brings the logic back in line
with existing build system conventions (CMake, Autotools, Meson):

* Absolute paths are used as-is.
* Relative paths are resolved relative to the install
  prefix path, rather than CWD.

Ecosystem context:
https://github.com/mesonbuild/meson/pull/9903

Signed-off-by: Eric Joldasov 
---
 lib/compiler/Maker.zig | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index 6cbe61a1b3509d633c48e083cdc6fdf853d306c9..b36f6e4e7da2388d368b6d1684c893f362c57a32 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -648,20 +648,31 @@ pub fn main(init: process.Init.Minimal) !void {
         .sub_path = "zig-out",
     };
 
-    const install_lib_path: Path = if (override_lib_dir) |cwd_relative| .{
-        .root_dir = .cwd(),
-        .sub_path = cwd_relative,
-    } else try install_prefix_path.join(arena, "lib");
+    // These three overrides are meant to be relative to the install prefix,
+    // not current working directory, unless absolute paths are used.
+    const install_lib_path: Path = if (override_lib_dir) |lib_dir|
+        if (Dir.path.isAbsolute(lib_dir)) .{
+            .root_dir = .cwd(),
+            .sub_path = lib_dir,
+        } else try install_prefix_path.join(arena, lib_dir)
+    else
+        try install_prefix_path.join(arena, "lib");
 
-    const install_bin_path: Path = if (override_bin_dir) |cwd_relative| .{
-        .root_dir = .cwd(),
-        .sub_path = cwd_relative,
-    } else try install_prefix_path.join(arena, "bin");
+    const install_bin_path: Path = if (override_bin_dir) |bin_dir|
+        if (Dir.path.isAbsolute(bin_dir)) .{
+            .root_dir = .cwd(),
+            .sub_path = bin_dir,
+        } else try install_prefix_path.join(arena, bin_dir)
+    else
+        try install_prefix_path.join(arena, "bin");
 
-    const install_include_path: Path = if (override_include_dir) |cwd_relative| .{
-        .root_dir = .cwd(),
-        .sub_path = cwd_relative,
-    } else try install_prefix_path.join(arena, "include");
+    const install_include_path: Path = if (override_include_dir) |include_dir|
+        if (Dir.path.isAbsolute(include_dir)) .{
+            .root_dir = .cwd(),
+            .sub_path = include_dir,
+        } else try install_prefix_path.join(arena, include_dir)
+    else
+        try install_prefix_path.join(arena, "include");
 
     const now = Io.Clock.Timestamp.now(io, .awake);
 
-- 
2.54.0


From ce96dcceab7731f63534425f1d25bfe9be014847 Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Mon, 3 Aug 2026 14:35:39 -0400
Subject: [PATCH 138/215] fix(Io.Dispatch): node = .{}, mutex deinit, wrong
 canceled

In most of the file `node: std.DoublyLinkedList.Node` is
default-initialized as `.{}` rather than `undefined`. I don't believe
this resolves any crashes for me, but it seems incorrect.

If `backing_allocator_needs_mutex` is `true` and the backing allocator
has been used nontrivially; for example in creating a `Group`, the
current `Dispatch.deinit()` code segfaults. Since the error also goes away
when `backing_allocator_needs_mutex` is false, I believe remembering to
call `deinit()` on the mutex is the fix.

Canceling a sleep call currently crashes because of a soundness issue:
The `@fieldParentPtr` type punning in `SleepWaiter.canceled` cannot be
replaced by `Futex.Waiter.canceled`. For me, the failure winds up being in
`waiter.remove()` meeting a node whose `prev` field is mostly `0xaa`,
which made this one a real pain to fix.
---
 lib/std/Io/Dispatch.zig | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig
index 4f58bc8bdf7645ae97bd1131a13974552d07e7a8..1cbbcbaef64a35185ab51a6cc17abc56b4d246af 100644
--- a/lib/std/Io/Dispatch.zig
+++ b/lib/std/Io/Dispatch.zig
@@ -580,6 +580,7 @@ pub fn deinit(ev: *Evented) void {
     ev.stderr_mutex.deinit();
     for (&ev.futexes) |*futex| futex.deinit();
     ev.exit_semaphore.as_object().release();
+    ev.backing_allocator_mutex.deinit();
     ev.backing_allocator.free(ev.main_loop_stack[0..main_loop_stack_size]);
     ev.queue.as_object().release();
 }
@@ -825,7 +826,7 @@ const Mutex = struct {
         sleeper: Sleeper = undefined,
         cancelable: Cancelable,
         mutex: *Mutex,
-        node: std.DoublyLinkedList.Node = undefined,
+        node: std.DoublyLinkedList.Node = .{},
 
         fn add(context: ?*anyopaque) callconv(.c) void {
             const waiter: *Waiter = @ptrCast(@alignCast(context));
@@ -4714,7 +4715,7 @@ fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
         return ev.yield(.{ .after = ev.timeFromTimeout(timeout) });
     };
     var waiter: SleepWaiter = .{
-        .cancelable = .{ .queue = queue, .cancel = &Futex.Waiter.canceled },
+        .cancelable = .{ .queue = queue, .cancel = &SleepWaiter.canceled },
         .timer = timer,
     };
     timer.as_object().set_context(&waiter);
-- 
2.54.0


From 5d2ad0b021f1926f09039827077bf1bd55f83df7 Mon Sep 17 00:00:00 2001
From: Ari Becker 
Date: Wed, 5 Aug 2026 03:03:24 +0200
Subject: [PATCH 139/215] Support checking IP addresses in certificate subject
 alternate names (#36301)

I was trying to get Zig to verify a local TLS certificate (i.e. for "127.0.0.1") issued by [mkcert](https://github.com/FiloSottile/mkcert) and was surprised to see that Zig did not verify it. It turns out that `std` currently only validates DNS hostnames in certificates, and not yet IP addresses.

There are, of course, other use-cases for TLS certificates for IP addresses, such as for DNS over TLS (public example: `openssl s_client -connect 1.1.1.1:443 | openssl x509 -text -noout`).

This PR allows `std.crypto.Certificate` to verify TLS certificates when they present an IP address as a subject alternate name.

Prior art: [Golang standard library crypto/x509](https://cs.opensource.google/go/go/+/refs/tags/go1.26.5:src/crypto/x509/verify.go;l=942)

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36301
Reviewed-by: Andrew Kelley 
---
 lib/std/crypto/Certificate.zig | 56 ++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index aa36b73ac3e36e51bea58c59fea780d1cc222ae8..68b0d1dfc6f6acc6fcb1eae27468510ddd9fbf9a 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -175,6 +175,8 @@ pub const GeneralNameTag = enum(u5) {
     _,
 };
 
+const net = @import("../Io/net.zig");
+
 pub const Parsed = struct {
     certificate: Certificate,
     issuer_slice: Slice,
@@ -315,6 +317,7 @@ pub const Parsed = struct {
         // what to check. Otherwise, only the common name is checked.
         const subject_alt_name = parsed_subject.subjectAltName();
         if (subject_alt_name.len == 0) {
+            // note: checkIpAddress is intentionally omitted, as it is not permitted in the common name field anyway.
             if (checkHostName(host_name, parsed_subject.commonName())) {
                 return;
             } else {
@@ -332,6 +335,10 @@ pub const Parsed = struct {
                     const dns_name = subject_alt_name[general_name.slice.start..general_name.slice.end];
                     if (checkHostName(host_name, dns_name)) return;
                 },
+                .iPAddress => {
+                    const ip_address = subject_alt_name[general_name.slice.start..general_name.slice.end];
+                    if (checkIpAddress(host_name, ip_address)) return;
+                },
                 else => {},
             }
         }
@@ -376,6 +383,22 @@ pub const Parsed = struct {
 
         return false;
     }
+
+    // Check IP address according to RFC 5280 §4.2.1.6.
+    fn checkIpAddress(host_name: []const u8, ip_address: []const u8) bool {
+        switch (ip_address.len) {
+            4 => {
+                // port is irrelevant to SAN matching, so 0 is a harmless placeholder.
+                const address = net.Ip4Address.parse(host_name, 0) catch return false;
+                return mem.eql(u8, &address.bytes, ip_address);
+            },
+            16 => {
+                const address = net.Ip6Address.parse(host_name, 0) catch return false;
+                return mem.eql(u8, &address.bytes, ip_address);
+            },
+            else => return false, // a malformed certificate, neither 4 nor 16 octets
+        }
+    }
 };
 
 test "Parsed.checkHostName RFC 6125 compliance" {
@@ -417,6 +440,39 @@ test "Parsed.checkHostName RFC 6125 compliance" {
     try expectEqual(false, Parsed.checkHostName("example.com", "*."));
 }
 
+test "Parsed.checkIpAddress RFC 5280 4.2.1.6 compliance" {
+    const expectEqual = std.testing.expectEqual;
+
+    // Exact match positive tests
+    try expectEqual(true, Parsed.checkIpAddress("127.0.0.1", &[4]u8{ 127, 0, 0, 1 }));
+    try expectEqual(true, Parsed.checkIpAddress("0:0:0:0:0:0:0:1", &[16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }));
+
+    // Mismatches should not pass
+    try expectEqual(false, Parsed.checkIpAddress("1.2.3.4", &[4]u8{ 5, 6, 7, 8 }));
+    try expectEqual(false, Parsed.checkIpAddress("0:0:0:0:0:0:0:1", &[16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }));
+
+    // IPv6: the hostname may be in short-form and should match the exact 16 octets specified in the SAN
+    try expectEqual(true, Parsed.checkIpAddress("::1", &[16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }));
+
+    // IPv6: do not match when using DNS64 / NAT64 (i.e. 64:ff9b::/96)
+    // the RFC requires exact octet matches, so this is likely surprising and wrong. The decision here is to fail-safe out of an abundance of caution.
+    // The test assertions are included not to harden on this behavior, but to show that this use-case was considered.
+    // This check may become more lenient in the future if a valid use-case is found.
+    try expectEqual(false, Parsed.checkIpAddress("64:ff9b::192.0.2.10", &[4]u8{ 192, 0, 2, 10 }));
+    try expectEqual(false, Parsed.checkIpAddress("::ffff:127.0.0.1", &[4]u8{ 127, 0, 0, 1 }));
+
+    // Malformed SAN lengths (not 4 or 16 octets) never match.
+    try expectEqual(false, Parsed.checkIpAddress("127.0.0", &[_]u8{ 127, 0, 0 }));
+    try expectEqual(false, Parsed.checkIpAddress("127.0.0.1.0", &[_]u8{ 127, 0, 0, 1, 0 }));
+
+    // A non-parseable host_name never matches.
+    try expectEqual(false, Parsed.checkIpAddress("not-an-ip", &[4]u8{ 127, 0, 0, 1 }));
+
+    // Edge cases - empty strings
+    try expectEqual(false, Parsed.checkIpAddress("", ""));
+    try expectEqual(false, Parsed.checkIpAddress("127.0.0.1", ""));
+}
+
 pub const ParseError = der.Element.ParseError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError;
 
 pub fn parse(cert: Certificate) ParseError!Parsed {
-- 
2.54.0


From 867ab50575b89de123c852aa74b481966f00d8eb Mon Sep 17 00:00:00 2001
From: Mick Sayson 
Date: Mon, 13 Jul 2026 15:41:54 -0700
Subject: [PATCH 140/215] fix compiler crash on mem.doNotOptimize on SPIR-V

---
 lib/std/mem.zig | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 46e8347edec959724ef407bfb1c3b6981b3e9142..84eef40ec8d317fe2b5ae070c6b9fa0dccf92a08 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -4810,21 +4810,32 @@ pub fn doNotOptimizeAway(val: anytype) void {
         return;
     }
 
-    const max_gp_register_bits = @bitSizeOf(c_long);
     switch (@typeInfo(@TypeOf(val))) {
         .void, .null, .comptime_int, .comptime_float => return,
         .@"enum" => doNotOptimizeAway(@backingInt(val)),
         .bool => doNotOptimizeAway(@intFromBool(val)),
-        .int => |int| if (int.bits <= max_gp_register_bits) {
-            const val2 = @as(
-                @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))),
-                val,
-            );
-            asm volatile (""
-                :
-                : [_] "r" (val2),
-            );
-        } else doNotOptimizeAway(&val),
+        .int => |int| {
+            // SPIR-V targets do not have registers per se, they have values
+            // tied to IDs that can be passed to valid instructions. Some
+            // SPIR-V targets do not define c_long, so we just allow any sized
+            // integer on these targets
+            const val_fits_in_gp_register = builtin.target.cpu.arch.isSpirV() or fits: {
+                const max_gp_register_bits = @bitSizeOf(c_long);
+                break :fits int.bits <= max_gp_register_bits;
+            };
+            if (val_fits_in_gp_register) {
+                const val2 = @as(
+                    @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))),
+                    val,
+                );
+                asm volatile (""
+                    :
+                    : [_] "r" (val2),
+                );
+            } else {
+                doNotOptimizeAway(&val);
+            }
+        },
         .float => |float| switch (float.bits) {
             else => comptime unreachable,
             16, 80, 128 => doNotOptimizeAway(&val),
-- 
2.54.0


From 6afdd3370a50fe4a20108363b6b7d31e93765cd2 Mon Sep 17 00:00:00 2001
From: Hila Friedman 
Date: Fri, 26 Jun 2026 15:50:53 +0300
Subject: [PATCH 141/215] handle non-reflexive types in std.mem.eql and
 std.mem.findDiff

---
 lib/std/mem.zig | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 84eef40ec8d317fe2b5ae070c6b9fa0dccf92a08..2d0d5f7d8bbb5653dbdaf55ee95c2cf85fa47b5e 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -756,7 +756,8 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
     }
 
     if (a.len != b.len) return false;
-    if (a.len == 0 or a.ptr == b.ptr) return true;
+    if (a.len == 0) return true;
+    if (@typeInfo(T) != .float and a.ptr == b.ptr) return true;
 
     for (a, b) |a_elem, b_elem| {
         if (a_elem != b_elem) return false;
@@ -781,6 +782,9 @@ test eql {
 
     try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} }));
     try testing.expect(!eql(void, &.{{}}, &.{ {}, {} }));
+
+    const x: [3]f64 = .{ 42.0, math.nan(f64), 3.1415 };
+    try testing.expect(!eql(f64, &x, &x));
 }
 
 /// std.mem.eql heavily optimized for slices of bytes.
@@ -850,20 +854,25 @@ pub const indexOfDiff = findDiff;
 /// Compares two slices and returns the index of the first inequality.
 /// Returns null if the slices are equal.
 pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize {
-    const shortest = @min(a.len, b.len);
-    if (a.ptr == b.ptr)
-        return if (a.len == b.len) null else shortest;
-    var index: usize = 0;
-    while (index < shortest) : (index += 1) if (a[index] != b[index]) return index;
-    return if (a.len == b.len) null else shortest;
+    const shorter = @min(a.len, b.len);
+    if (@typeInfo(T) != .float and a.ptr == b.ptr) {
+        return if (a.len == b.len) null else shorter;
+    }
+    for (a[0..shorter], b[0..shorter], 0..) |a_elem, b_elem, i| {
+        if (a_elem != b_elem) return i;
+    }
+    return if (a.len == b.len) null else shorter;
 }
 
 test findDiff {
-    try testing.expectEqual(findDiff(u8, "one", "one"), null);
-    try testing.expectEqual(findDiff(u8, "one two", "one"), 3);
-    try testing.expectEqual(findDiff(u8, "one", "one two"), 3);
-    try testing.expectEqual(findDiff(u8, "one twx", "one two"), 6);
-    try testing.expectEqual(findDiff(u8, "xne", "one"), 0);
+    try testing.expectEqual(null, findDiff(u8, "one", "one"));
+    try testing.expectEqual(3, findDiff(u8, "one two", "one"));
+    try testing.expectEqual(3, findDiff(u8, "one", "one two"));
+    try testing.expectEqual(6, findDiff(u8, "one twx", "one two"));
+    try testing.expectEqual(0, findDiff(u8, "xne", "one"));
+
+    const x: [3]f64 = .{ 42.0, math.nan(f64), 3.1415 };
+    try testing.expectEqual(1, findDiff(f64, &x, &x));
 }
 
 /// Takes a sentinel-terminated pointer and returns a slice preserving pointer attributes.
-- 
2.54.0


From 2bc025186677145805cf97ef75e50c5711597f20 Mon Sep 17 00:00:00 2001
From: cheesecakecatttt 
Date: Sat, 11 Jul 2026 07:35:44 +0000
Subject: [PATCH 142/215] link: emit -NOENTRY for disabled entry on COFF

---
 src/link/Lld.zig | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/link/Lld.zig b/src/link/Lld.zig
index cf64d3fd5bc51817cc86a7554ac65ee7aa53e373..d9d2e4913973e48ad6764ae58d123e5a42836a55 100644
--- a/src/link/Lld.zig
+++ b/src/link/Lld.zig
@@ -394,7 +394,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
     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
+        // This logic isn't quite right for default 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,
@@ -503,6 +503,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
 
         if (entry_name) |name| {
             try argv.append(try arena.print("-ENTRY:{s}", .{name}));
+        } else if (coff.entry == .disabled) {
+            try argv.append("-NOENTRY");
         }
 
         if (coff.repro) {
-- 
2.54.0


From b18436dfad20428e661197a71f4dc12143f4dac0 Mon Sep 17 00:00:00 2001
From: Meghan Denny 
Date: Wed, 15 Jul 2026 16:48:50 -0700
Subject: [PATCH 143/215] std.crypto.sign.ecdsa: pub Curve and Hash parameters

---
 lib/std/crypto/ecdsa.zig | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig
index 8977851b44ea04596ff686ec46fa576aa9b9693f..77e0349341168fd3d6e0b68979d95cf45753bc4f 100644
--- a/lib/std/crypto/ecdsa.zig
+++ b/lib/std/crypto/ecdsa.zig
@@ -24,14 +24,17 @@ pub const EcdsaSecp256k1Sha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.sha2.Sh
 pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.composition.Sha256oSha256);
 
 /// Elliptic Curve Digital Signature Algorithm (ECDSA).
-pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
-    const Prf = switch (Hash) {
+pub fn Ecdsa(comptime C: type, comptime H: type) type {
+    const Prf = switch (H) {
         sha3.Shake128 => sha3.KMac128,
         sha3.Shake256 => sha3.KMac256,
-        else => crypto.auth.hmac.Hmac(Hash),
+        else => crypto.auth.hmac.Hmac(H),
     };
 
     return struct {
+        pub const Curve = C;
+        pub const Hash = H;
+
         /// Length (in bytes) of optional random bytes, for non-deterministic signatures.
         pub const noise_length = Curve.scalar.encoded_length;
 
-- 
2.54.0


From fa515299f3b9bd9fc7aad4ad04dd862b1c925075 Mon Sep 17 00:00:00 2001
From: Meghan Denny 
Date: Tue, 14 Jul 2026 11:03:11 -0700
Subject: [PATCH 144/215] std.crypto.Certificate.rsa.encrypt: accept modulus by
 pointer

the expected sizes for modulus_len are 128, 256, 384, 512
---
 lib/std/crypto/Certificate.zig | 12 ++++++------
 lib/std/crypto/tls/Client.zig  |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index 68b0d1dfc6f6acc6fcb1eae27468510ddd9fbf9a..b725e932b418b36741ec2b4c38dbae7d6369c825 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -849,7 +849,7 @@ fn verifyRsa(
         inline 128, 256, 384, 512 => |modulus_len| {
             const public_key = rsa.PublicKey.fromBytes(exponent, modulus) catch
                 return error.CertificateSignatureInvalid;
-            rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len].*, msg, public_key, Hash) catch
+            rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len], msg, public_key, Hash) catch
                 return error.CertificateSignatureInvalid;
         },
         else => return error.CertificateSignatureUnsupportedBitCount,
@@ -1039,7 +1039,7 @@ pub const rsa = struct {
 
         pub fn concatVerify(
             comptime modulus_len: usize,
-            sig: [modulus_len]u8,
+            sig: *const [modulus_len]u8,
             msg: []const []const u8,
             public_key: PublicKey,
             comptime Hash: type,
@@ -1192,7 +1192,7 @@ pub const rsa = struct {
 
         pub fn verify(
             comptime modulus_len: usize,
-            sig: [modulus_len]u8,
+            sig: *const [modulus_len]u8,
             msg: []const u8,
             public_key: PublicKey,
             comptime Hash: type,
@@ -1202,7 +1202,7 @@ pub const rsa = struct {
 
         pub fn concatVerify(
             comptime modulus_len: usize,
-            sig: [modulus_len]u8,
+            sig: *const [modulus_len]u8,
             msg: []const []const u8,
             public_key: PublicKey,
             comptime Hash: type,
@@ -1348,8 +1348,8 @@ pub const rsa = struct {
 
     const EncryptError = error{MessageTooLong};
 
-    fn encrypt(comptime modulus_len: usize, msg: [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {
-        const m = Fe.fromBytes(public_key.n, &msg, .big) catch return error.MessageTooLong;
+    fn encrypt(comptime modulus_len: usize, msg: *const [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 {
+        const m = Fe.fromBytes(public_key.n, msg, .big) catch return error.MessageTooLong;
         const e = public_key.n.powPublic(m, public_key.e) catch unreachable;
         var res: [modulus_len]u8 = undefined;
         e.toBytes(&res, .big) catch unreachable;
diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig
index 1eb3aca852c0fb6025ee35dcf7cee896606af4df..0fbb28661ac560b14aa17f90bda007cbea574191 100644
--- a/lib/std/crypto/tls/Client.zig
+++ b/lib/std/crypto/tls/Client.zig
@@ -1588,7 +1588,7 @@ const CertificatePublicKey = struct {
                     inline 128, 256, 384, 512 => |modulus_len| {
                         const key: PublicKey = try .fromBytes(exponent, modulus);
                         const sig = RsaSignature.fromBytes(modulus_len, encoded_sig);
-                        try RsaSignature.concatVerify(modulus_len, sig, msg, key, Hash);
+                        try RsaSignature.concatVerify(modulus_len, &sig, msg, key, Hash);
                     },
                     else => return error.TlsBadRsaSignatureBitCount,
                 }
-- 
2.54.0


From f611a72e2eb7bba2ef5fc5f578ced3c711ff7374 Mon Sep 17 00:00:00 2001
From: Meghan Denny 
Date: Tue, 14 Jul 2026 01:17:41 -0700
Subject: [PATCH 145/215] std.crypto.Certificate.rsa.PKCS1v1_5Signature: add
 DER for more hashes

---
 lib/std/crypto/Certificate.zig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index b725e932b418b36741ec2b4c38dbae7d6369c825..f0d18e58a130cd18d0eb8c00dba3b6f32903c802 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -1243,6 +1243,11 @@ pub const rsa = struct {
             //    DigestInfo value (see the notes below) and let tLen be the length
             //    in octets of T.
             const hash_der: []const u8 = &switch (Hash) {
+                crypto.hash.Md5 => .{
+                    0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86,
+                    0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00,
+                    0x04, 0x10,
+                },
                 crypto.hash.Sha1 => .{
                     0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
                     0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
@@ -1267,6 +1272,16 @@ pub const rsa = struct {
                     0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
                     0x00, 0x04, 0x40,
                 },
+                crypto.hash.sha3.Sha3_256 => .{
+                    0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
+                    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05,
+                    0x00, 0x04, 0x20,
+                },
+                crypto.hash.sha3.Sha3_512 => .{
+                    0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86,
+                    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05,
+                    0x00, 0x04, 0x40,
+                },
                 else => comptime unreachable,
             };
             em_index -= hash_der.len;
-- 
2.54.0


From e88566253d65a83e3564f95504fe034b4287c340 Mon Sep 17 00:00:00 2001
From: Meghan Denny 
Date: Tue, 19 May 2026 17:01:54 -0700
Subject: [PATCH 146/215] sema: improve @errorCast safety check message

---
 lib/std/debug.zig                             |  4 +++
 lib/std/debug/no_panic.zig                    |  5 +++
 lib/std/debug/simple_panic.zig                | 31 +++++++++++++++++++
 src/Sema.zig                                  | 10 +++---
 src/Zcu.zig                                   |  2 ++
 .../bad_panic_call_signature.zig              |  1 +
 .../bad_panic_generic_signature.zig           |  1 +
 ...rCast error not present in destination.zig |  2 +-
 ...ast error union casted to disjoint set.zig |  2 +-
 .../incremental/change_panic_handler_explicit |  3 ++
 10 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index faeed5f667c9a8dc4ec0f38ef2a829b5f42dff3c..59a8dcd9eae1cf7ba40a1e5e9c50a683186c322c 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -151,6 +151,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type {
             @branchHint(.cold);
             call("invalid error code", @returnAddress());
         }
+        pub fn unexpectedErrorCode(err: anyerror) noreturn {
+            @branchHint(.cold);
+            std.debug.panicExtra(@returnAddress(), "unexpected error code, found error.{s}", .{@errorName(err)});
+        }
         pub fn integerOutOfBounds() noreturn {
             @branchHint(.cold);
             call("integer does not fit in destination type", @returnAddress());
diff --git a/lib/std/debug/no_panic.zig b/lib/std/debug/no_panic.zig
index d47c9799a990e0d53cdf61e735b008deb355fd44..772fb7e496c44a4bf9f566ff17d49826b319cceb 100644
--- a/lib/std/debug/no_panic.zig
+++ b/lib/std/debug/no_panic.zig
@@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn {
     @trap();
 }
 
+pub fn unexpectedErrorCode(_: anyerror) noreturn {
+    @branchHint(.cold);
+    @trap();
+}
+
 pub fn integerOutOfBounds() noreturn {
     @branchHint(.cold);
     @trap();
diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig
index af7231251aa0e9bd94ef1eef36280d110b4d2019..8453aadbb985766f749199c0bac617cb858afe04 100644
--- a/lib/std/debug/simple_panic.zig
+++ b/lib/std/debug/simple_panic.zig
@@ -20,110 +20,141 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn {
 }
 
 pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
+    @branchHint(.cold);
     _ = found;
     call("sentinel mismatch", null);
 }
 
 pub fn unwrapError(err: anyerror) noreturn {
+    @branchHint(.cold);
     _ = &err;
     call("attempt to unwrap error", null);
 }
 
 pub fn outOfBounds(index: usize, len: usize) noreturn {
+    @branchHint(.cold);
     _ = index;
     _ = len;
     call("index out of bounds", null);
 }
 
 pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
+    @branchHint(.cold);
     _ = start;
     _ = end;
     call("start index is larger than end index", null);
 }
 
 pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
+    @branchHint(.cold);
     _ = accessed;
     call("access of inactive union field", null);
 }
 
 pub fn sliceCastLenRemainder(src_len: usize) noreturn {
+    @branchHint(.cold);
     _ = src_len;
     call("slice length does not divide exactly into destination elements", null);
 }
 
 pub fn reachedUnreachable() noreturn {
+    @branchHint(.cold);
     call("reached unreachable code", null);
 }
 
 pub fn unwrapNull() noreturn {
+    @branchHint(.cold);
     call("attempt to use null value", null);
 }
 
 pub fn castToNull() noreturn {
+    @branchHint(.cold);
     call("cast causes pointer to be null", null);
 }
 
 pub fn incorrectAlignment() noreturn {
+    @branchHint(.cold);
     call("incorrect alignment", null);
 }
 
 pub fn invalidErrorCode() noreturn {
+    @branchHint(.cold);
     call("invalid error code", null);
 }
 
+pub fn unexpectedErrorCode(err: anyerror) noreturn {
+    @branchHint(.cold);
+    _ = err;
+    call("unexpected error code", null);
+}
+
 pub fn integerOutOfBounds() noreturn {
+    @branchHint(.cold);
     call("integer does not fit in destination type", null);
 }
 
 pub fn integerOverflow() noreturn {
+    @branchHint(.cold);
     call("integer overflow", null);
 }
 
 pub fn shlOverflow() noreturn {
+    @branchHint(.cold);
     call("left shift overflowed bits", null);
 }
 
 pub fn shrOverflow() noreturn {
+    @branchHint(.cold);
     call("right shift overflowed bits", null);
 }
 
 pub fn divideByZero() noreturn {
+    @branchHint(.cold);
     call("division by zero", null);
 }
 
 pub fn exactDivisionRemainder() noreturn {
+    @branchHint(.cold);
     call("exact division produced remainder", null);
 }
 
 pub fn integerPartOutOfBounds() noreturn {
+    @branchHint(.cold);
     call("integer part of floating point value out of bounds", null);
 }
 
 pub fn corruptSwitch() noreturn {
+    @branchHint(.cold);
     call("switch on corrupt value", null);
 }
 
 pub fn shiftRhsTooBig() noreturn {
+    @branchHint(.cold);
     call("shift amount is greater than the type size", null);
 }
 
 pub fn invalidEnumValue() noreturn {
+    @branchHint(.cold);
     call("invalid enum value", null);
 }
 
 pub fn forLenMismatch() noreturn {
+    @branchHint(.cold);
     call("for loop over objects with non-equal lengths", null);
 }
 
 pub fn copyLenMismatch() noreturn {
+    @branchHint(.cold);
     call("source and destination have non-equal lengths", null);
 }
 
 pub fn memcpyAlias() noreturn {
+    @branchHint(.cold);
     call("@memcpy arguments alias", null);
 }
 
 pub fn noreturnReturned() noreturn {
+    @branchHint(.cold);
     call("'noreturn' function returned", null);
 }
 
diff --git a/src/Sema.zig b/src/Sema.zig
index 96bb93f02bcd78185e14c04f40ab832fc09868b4..b2bdfc6abf88324c01e74d78dae9473c5143ac8e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -21675,16 +21675,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
             const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err);
             if (result == .disjoint) {
                 // Error must be zero.
-                try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code);
+                try sema.addSafetyCheckCall(block, src, is_zero, .@"panic.unexpectedErrorCode", &.{err_code_inst});
             } else {
                 // Error must be in destination set or zero.
                 const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);
                 const ok = try block.addBinOp(.bit_or, has_value, is_zero);
-                try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
+                try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst});
             }
         } else {
             const ok = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst);
-            try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
+            try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst});
         }
     }
 
@@ -35031,7 +35031,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ
         }),
 
         // `fn (anyerror) noreturn`
-        .@"panic.unwrapError" => try pt.funcType(.{
+        .@"panic.unwrapError",
+        .@"panic.unexpectedErrorCode",
+        => try pt.funcType(.{
             .param_types = &.{.anyerror_type},
             .return_type = .noreturn_type,
         }),
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 0c231862cb0720fec4419115e08b712eacbdcf6f..92659d3253b60fb26eddac3eadf3ce9ec6ba1499 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -503,6 +503,7 @@ pub const StdLangDecl = enum {
     @"panic.castToNull",
     @"panic.incorrectAlignment",
     @"panic.invalidErrorCode",
+    @"panic.unexpectedErrorCode",
     @"panic.integerOutOfBounds",
     @"panic.integerOverflow",
     @"panic.shlOverflow",
@@ -593,6 +594,7 @@ pub const StdLangDecl = enum {
             .@"panic.castToNull",
             .@"panic.incorrectAlignment",
             .@"panic.invalidErrorCode",
+            .@"panic.unexpectedErrorCode",
             .@"panic.integerOutOfBounds",
             .@"panic.integerOverflow",
             .@"panic.shlOverflow",
diff --git a/test/cases/compile_errors/bad_panic_call_signature.zig b/test/cases/compile_errors/bad_panic_call_signature.zig
index 6d88f1b8781c6db162037a42564cbe3fefc06179..fdfc8a8c3bad266235f5458dbe476bded279352c 100644
--- a/test/cases/compile_errors/bad_panic_call_signature.zig
+++ b/test/cases/compile_errors/bad_panic_call_signature.zig
@@ -15,6 +15,7 @@ pub const panic = struct {
     pub const castToNull = simple_panic.castToNull;
     pub const incorrectAlignment = simple_panic.incorrectAlignment;
     pub const invalidErrorCode = simple_panic.invalidErrorCode;
+    pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
     pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
     pub const integerOverflow = simple_panic.integerOverflow;
     pub const shlOverflow = simple_panic.shlOverflow;
diff --git a/test/cases/compile_errors/bad_panic_generic_signature.zig b/test/cases/compile_errors/bad_panic_generic_signature.zig
index 8ef4810745ce45855bad0262e1a1bef0ca5db414..0dba45036e36bb73e44c046a8a3b0a8dd645dab9 100644
--- a/test/cases/compile_errors/bad_panic_generic_signature.zig
+++ b/test/cases/compile_errors/bad_panic_generic_signature.zig
@@ -11,6 +11,7 @@ pub const panic = struct {
     pub const castToNull = simple_panic.castToNull;
     pub const incorrectAlignment = simple_panic.incorrectAlignment;
     pub const invalidErrorCode = simple_panic.invalidErrorCode;
+    pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode;
     pub const integerOutOfBounds = simple_panic.integerOutOfBounds;
     pub const integerOverflow = simple_panic.integerOverflow;
     pub const shlOverflow = simple_panic.shlOverflow;
diff --git a/test/cases/safety/@errorCast error not present in destination.zig b/test/cases/safety/@errorCast error not present in destination.zig
index 3ae83186023587a707594a45f89e723c338265c9..2e0e4f22538db11499f89cc82b996ff20a582c34 100644
--- a/test/cases/safety/@errorCast error not present in destination.zig	
+++ b/test/cases/safety/@errorCast error not present in destination.zig	
@@ -2,7 +2,7 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "invalid error code")) {
+    if (std.mem.eql(u8, message, "unexpected error code, found error.B")) {
         std.process.exit(0);
     }
     std.process.exit(1);
diff --git a/test/cases/safety/@errorCast error union casted to disjoint set.zig b/test/cases/safety/@errorCast error union casted to disjoint set.zig
index 0bf9311be764390a109d85f146868a1ab6a5b265..2f8238698a8afee3d9cdd7ba05f0f274b05b6241 100644
--- a/test/cases/safety/@errorCast error union casted to disjoint set.zig	
+++ b/test/cases/safety/@errorCast error union casted to disjoint set.zig	
@@ -2,7 +2,7 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "invalid error code")) {
+    if (std.mem.eql(u8, message, "unexpected error code, found error.Bar")) {
         std.process.exit(0);
     }
     std.process.exit(1);
diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit
index f748a57afc43e7d18e5458549a18c173d21dc56c..3735cfd86c0116ce130481c56f60d6816174d00f 100644
--- a/test/incremental/change_panic_handler_explicit
+++ b/test/incremental/change_panic_handler_explicit
@@ -23,6 +23,7 @@ pub const panic = struct {
     pub const castToNull = no_panic.castToNull;
     pub const incorrectAlignment = no_panic.incorrectAlignment;
     pub const invalidErrorCode = no_panic.invalidErrorCode;
+    pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
     pub const integerOutOfBounds = no_panic.integerOutOfBounds;
     pub const shlOverflow = no_panic.shlOverflow;
     pub const shrOverflow = no_panic.shrOverflow;
@@ -72,6 +73,7 @@ pub const panic = struct {
     pub const castToNull = no_panic.castToNull;
     pub const incorrectAlignment = no_panic.incorrectAlignment;
     pub const invalidErrorCode = no_panic.invalidErrorCode;
+    pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
     pub const integerOutOfBounds = no_panic.integerOutOfBounds;
     pub const shlOverflow = no_panic.shlOverflow;
     pub const shrOverflow = no_panic.shrOverflow;
@@ -121,6 +123,7 @@ pub const panic = struct {
     pub const castToNull = no_panic.castToNull;
     pub const incorrectAlignment = no_panic.incorrectAlignment;
     pub const invalidErrorCode = no_panic.invalidErrorCode;
+    pub const unexpectedErrorCode = no_panic.unexpectedErrorCode;
     pub const integerOutOfBounds = no_panic.integerOutOfBounds;
     pub const shlOverflow = no_panic.shlOverflow;
     pub const shrOverflow = no_panic.shrOverflow;
-- 
2.54.0


From ab4028d5796c68ca3aeb649e475bceff394942fc Mon Sep 17 00:00:00 2001
From: Krzysztof Wolicki 
Date: Tue, 28 Jul 2026 18:13:17 +0200
Subject: [PATCH 147/215] Update usages of most deprecated APIs

In particular renames of `std.mem.indexOf` family to `std.mem.find`
and generic unmanaged containers
---
 lib/build-web/time_report.zig             |  6 ++---
 lib/compiler/Maker.zig                    |  2 +-
 lib/compiler/Maker/Fetch.zig              |  6 ++---
 lib/compiler/Maker/Fetch/git.zig          | 12 ++++-----
 lib/compiler/Maker/Step/Run.zig           |  4 +--
 lib/compiler/configurer.zig               |  2 +-
 lib/compiler/resinator/compile.zig        |  6 ++---
 lib/compiler/resinator/cvtres.zig         |  2 +-
 lib/compiler/resinator/errors.zig         |  2 +-
 lib/compiler/resinator/source_mapping.zig |  2 +-
 lib/docs/wasm/html_render.zig             |  2 +-
 lib/docs/wasm/main.zig                    |  6 ++---
 lib/docs/wasm/markdown/Parser.zig         | 20 +++++++-------
 lib/fuzzer.zig                            |  2 +-
 lib/std/Build.zig                         |  7 +++--
 lib/std/Build/Configuration.zig           |  8 +++---
 lib/std/Build/Module.zig                  |  4 +--
 lib/std/Build/Step/Compile.zig            |  2 +-
 lib/std/Io/Dispatch.zig                   |  6 ++---
 lib/std/Io/Threaded.zig                   | 10 +++----
 lib/std/Uri.zig                           |  8 +++---
 lib/std/array_hash_map.zig                | 14 +++++-----
 lib/std/crypto/Certificate.zig            |  6 ++---
 lib/std/fs/path.zig                       |  4 +--
 lib/std/heap/SafeAllocator.zig            |  2 +-
 lib/std/http/Server.zig                   |  2 +-
 lib/std/mem.zig                           | 32 +++++++++++------------
 lib/std/os/linux/IoUring/test.zig         |  2 +-
 lib/std/tar/Writer.zig                    |  2 +-
 lib/std/tar/test.zig                      |  6 ++---
 lib/std/testing.zig                       |  2 +-
 lib/std/testing/Smith.zig                 |  2 +-
 lib/std/zig.zig                           |  2 +-
 lib/std/zig/Ast/Render.zig                | 10 +++----
 lib/std/zig/llvm/Builder.zig              |  2 +-
 lib/std/zip.zig                           |  2 +-
 src/Air.zig                               |  2 +-
 src/IncrementalDebugServer.zig            |  8 +++---
 src/InternPool.zig                        |  6 ++---
 src/Sema.zig                              |  2 +-
 src/Value.zig                             |  2 +-
 src/Zcu.zig                               |  4 +--
 src/Zcu/PerThread.zig                     |  2 +-
 src/codegen/aarch64/Assemble.zig          |  2 +-
 src/codegen/aarch64/Select.zig            |  2 +-
 src/codegen/c.zig                         |  4 +--
 src/codegen/riscv64/CodeGen.zig           |  6 ++---
 src/codegen/x86_64/CodeGen.zig            | 30 ++++++++++-----------
 src/codegen/x86_64/Lower.zig              | 10 +++----
 src/codegen/x86_64/Mir.zig                |  6 ++---
 src/codegen/x86_64/abi.zig                |  2 +-
 src/codegen/x86_64/encoder.zig            |  2 +-
 src/libs/mingw/Preprocessor.zig           |  4 +--
 src/libs/mingw/def.zig                    |  8 +++---
 src/libs/mingw/implib.zig                 |  2 +-
 src/link/Coff.zig                         | 14 +++++-----
 src/link/Elf.zig                          |  6 ++---
 src/link/Elf/Archive.zig                  |  2 +-
 src/link/Elf2.zig                         |  2 +-
 src/link/MachO.zig                        | 12 ++++-----
 src/link/MachO/Archive.zig                |  4 +--
 src/link/MachO/Symbol.zig                 |  2 +-
 src/link/MachO/dyld_info/Trie.zig         |  4 +--
 src/link/SpirV.zig                        | 26 +++++++++---------
 src/link/SpirV/dedup_types.zig            |  4 +--
 src/link/SpirV/prune_unused.zig           |  2 +-
 src/link/Wasm.zig                         |  8 +++---
 src/link/Wasm/Archive.zig                 |  2 +-
 src/link/Wasm/Flush.zig                   |  6 ++---
 src/main.zig                              |  6 ++---
 src/target.zig                            |  4 +--
 test/src/Cases.zig                        |  4 +--
 test/src/Debugger.zig                     |  4 +--
 test/src/ErrorTrace.zig                   |  2 +-
 test/src/Libc.zig                         |  4 +--
 test/src/Link.zig                         |  2 +-
 test/src/LlvmIr.zig                       |  4 +--
 test/src/RunTranslatedC.zig               |  2 +-
 test/src/StackTrace.zig                   |  2 +-
 test/src/TranslateC.zig                   |  4 +--
 test/src/convert-stack-trace.zig          |  6 ++---
 test/tests.zig                            | 18 ++++++-------
 tools/docgen.zig                          |  4 +--
 tools/doctest.zig                         | 16 ++++++------
 tools/fetch_them_macos_headers.zig        |  4 +--
 tools/incr-check.zig                      |  6 ++---
 tools/update_clang_options.zig            |  2 +-
 tools/update_crc_catalog.zig              |  2 +-
 88 files changed, 253 insertions(+), 250 deletions(-)

diff --git a/lib/build-web/time_report.zig b/lib/build-web/time_report.zig
index f6e641432c93f7c2dc60cc710903ee907f25c626..042919e301b27d9c0705ed50ef057ad2f15b0d96 100644
--- a/lib/build-web/time_report.zig
+++ b/lib/build-web/time_report.zig
@@ -84,7 +84,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
     defer gpa.free(slowest_decls);
 
     for (slowest_files) |*file_out| {
-        const i = std.mem.indexOfScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
+        const i = std.mem.findScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
         file_out.* = .{
             .name = trailing[0..i],
             .ns_sema = 0,
@@ -95,7 +95,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v
     }
 
     for (slowest_decls) |*decl_out| {
-        const i = std.mem.indexOfScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
+        const i = std.mem.findScalar(u8, trailing, 0) orelse @panic("malformed CompileResult message");
         const file_idx = std.mem.readInt(u32, trailing[i..][1..5], .little);
         const sema_count = std.mem.readInt(u32, trailing[i..][5..9], .little);
         const sema_ns = std.mem.readInt(u64, trailing[i..][9..17], .little);
@@ -258,7 +258,7 @@ pub fn runTestResultMessage(msg_bytes: []u8) error{OutOfMemory}!void {
     defer table_html.deinit(gpa);
 
     for (durations) |test_ns| {
-        const test_name_len = std.mem.indexOfScalar(u8, trailing[offset..], 0) orelse @panic("malformed RunTestResult message");
+        const test_name_len = std.mem.findScalar(u8, trailing[offset..], 0) orelse @panic("malformed RunTestResult message");
         const test_name = trailing[offset..][0..test_name_len];
         offset += test_name_len + 1;
         try table_html.print(gpa, "{f}", .{fmtEscapeHtml(test_name)});
diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index b36f6e4e7da2388d368b6d1684c893f362c57a32..1a3a37b6dc008e7c536ab91e505d7559addbc7bb 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -3109,7 +3109,7 @@ pub fn printErrorMessages(
         try stderr.setColor(.red);
         try writer.writeAll("error:");
         try stderr.setColor(.reset);
-        if (std.mem.indexOfScalar(u8, msg, '\n') == null) {
+        if (std.mem.findScalar(u8, msg, '\n') == null) {
             try writer.print(" {s}\n", .{msg});
         } else switch (multiline_errors) {
             .indent => {
diff --git a/lib/compiler/Maker/Fetch.zig b/lib/compiler/Maker/Fetch.zig
index 5b5c6f7ff4385ca7cb4d45adcd0233feb24e1bff..13a6cd08c00b72fbf9493ff5acea1631d2542d6a 100644
--- a/lib/compiler/Maker/Fetch.zig
+++ b/lib/compiler/Maker/Fetch.zig
@@ -1164,7 +1164,7 @@ const FileType = enum {
         if (cd_header[value_start] != '=') return null;
         value_start += 1;
 
-        var value_end = std.mem.indexOfPos(u8, cd_header, value_start, ";") orelse cd_header.len;
+        var value_end = std.mem.findPos(u8, cd_header, value_start, ";") orelse cd_header.len;
         if (cd_header[value_end - 1] == '\"') {
             value_end -= 1;
         }
@@ -1344,7 +1344,7 @@ fn unpackResource(
                 return f.fail(f.location_tok, try eb.addString("missing 'Content-Type' header"));
 
             // Extract the MIME type, ignoring charset and boundary directives
-            const mime_type_end = std.mem.indexOf(u8, content_type, ";") orelse content_type.len;
+            const mime_type_end = std.mem.find(u8, content_type, ";") orelse content_type.len;
             const mime_type = content_type[0..mime_type_end];
 
             if (ascii.eqlIgnoreCase(mime_type, "application/x-tar"))
@@ -1455,7 +1455,7 @@ fn unpackTarball(f: *Fetch, out_dir: Io.Dir, reader: *Io.Reader) RunError!Unpack
 
     var diagnostics: std.tar.Diagnostics = .{ .allocator = arena };
 
-    std.tar.pipeToFileSystem(io, out_dir, reader, .{
+    std.tar.extract(io, out_dir, reader, .{
         .diagnostics = &diagnostics,
         .strip_components = 0,
         .mode_mode = .ignore,
diff --git a/lib/compiler/Maker/Fetch/git.zig b/lib/compiler/Maker/Fetch/git.zig
index 2e040a81fe68c09eede82fac6ece736efe44cc60..89f5bb6d86f4ef592bb42bbe7584fb2e06863da4 100644
--- a/lib/compiler/Maker/Fetch/git.zig
+++ b/lib/compiler/Maker/Fetch/git.zig
@@ -336,7 +336,7 @@ pub const Repository = struct {
         fn next(iterator: *TreeIterator) !?Entry {
             if (iterator.pos == iterator.data.len) return null;
 
-            const mode_end = mem.indexOfScalarPos(u8, iterator.data, iterator.pos, ' ') orelse return error.InvalidTree;
+            const mode_end = mem.findScalarPos(u8, iterator.data, iterator.pos, ' ') orelse return error.InvalidTree;
             const mode: packed struct {
                 permission: u9,
                 unused: u3,
@@ -351,7 +351,7 @@ pub const Repository = struct {
             };
             iterator.pos = mode_end + 1;
 
-            const name_end = mem.indexOfScalarPos(u8, iterator.data, iterator.pos, 0) orelse return error.InvalidTree;
+            const name_end = mem.findScalarPos(u8, iterator.data, iterator.pos, 0) orelse return error.InvalidTree;
             const name = iterator.data[iterator.pos..name_end :0];
             iterator.pos = name_end + 1;
 
@@ -823,7 +823,7 @@ pub const Session = struct {
             value: ?[]const u8 = null,
 
             fn parse(data: []const u8) Capability {
-                return if (mem.indexOfScalar(u8, data, '=')) |separator_pos|
+                return if (mem.findScalar(u8, data, '=')) |separator_pos|
                     .{ .key = data[0..separator_pos], .value = data[separator_pos + 1 ..] }
                 else
                     .{ .key = data };
@@ -941,17 +941,17 @@ pub const Session = struct {
                 .flush => return null,
                 .data => |data| {
                     const ref_data = Packet.normalizeText(data);
-                    const oid_sep_pos = mem.indexOfScalar(u8, ref_data, ' ') orelse return error.InvalidRefPacket;
+                    const oid_sep_pos = mem.findScalar(u8, ref_data, ' ') orelse return error.InvalidRefPacket;
                     const oid = Oid.parse(it.format, data[0..oid_sep_pos]) catch return error.InvalidRefPacket;
 
-                    const name_sep_pos = mem.indexOfScalarPos(u8, ref_data, oid_sep_pos + 1, ' ') orelse ref_data.len;
+                    const name_sep_pos = mem.findScalarPos(u8, ref_data, oid_sep_pos + 1, ' ') orelse ref_data.len;
                     const name = ref_data[oid_sep_pos + 1 .. name_sep_pos];
 
                     var symref_target: ?[]const u8 = null;
                     var peeled: ?Oid = null;
                     var last_sep_pos = name_sep_pos;
                     while (last_sep_pos < ref_data.len) {
-                        const next_sep_pos = mem.indexOfScalarPos(u8, ref_data, last_sep_pos + 1, ' ') orelse ref_data.len;
+                        const next_sep_pos = mem.findScalarPos(u8, ref_data, last_sep_pos + 1, ' ') orelse ref_data.len;
                         const attribute = ref_data[last_sep_pos + 1 .. next_sep_pos];
                         if (mem.startsWith(u8, attribute, "symref-target:")) {
                             symref_target = attribute["symref-target:".len..];
diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig
index 56fea332016567473fb6a3fc6c385e92b6c28f91..7f74e76954f44e5b965955d5ff5113d07428b6a7 100644
--- a/lib/compiler/Maker/Step/Run.zig
+++ b/lib/compiler/Maker/Step/Run.zig
@@ -555,7 +555,7 @@ const FuzzTestRunner = struct {
 
     const Instance = struct {
         child: process.Child,
-        message: std.ArrayListAligned(u8, .@"4"),
+        message: std.array_list.Aligned(u8, .@"4"),
         broadcast_written: usize,
         stderr: std.ArrayList(u8),
         stdin_vec: [1][]u8,
@@ -2120,7 +2120,7 @@ fn fmtSnapshotIndicatorLine(buf: []const u8, index: usize) std.fmt.Alt(
 }
 
 fn snapshotIndicatorLine(line: FmtIndicatorLine, w: *std.Io.Writer) std.Io.Writer.Error!void {
-    const line_begin_index = if (std.mem.lastIndexOfScalar(u8, line.buf[0..line.index], '\n')) |line_begin|
+    const line_begin_index = if (std.mem.findScalarLast(u8, line.buf[0..line.index], '\n')) |line_begin|
         line_begin + 1
     else
         0;
diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig
index b956ee1716db56768de7e872b7d09345881651b3..e55c37dfcc4db03f4f4fadff8a641a6f5d0c6414 100644
--- a/lib/compiler/configurer.zig
+++ b/lib/compiler/configurer.zig
@@ -83,7 +83,7 @@ pub fn main(init: process.Init.Minimal) !void {
         if (mem.cutPrefix(u8, arg, "-D")) |option_contents| {
             if (option_contents.len == 0)
                 fatalWithHint("expected option name after '-D'", .{});
-            if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
+            if (mem.findScalar(u8, option_contents, '=')) |name_end| {
                 const option_name = option_contents[0..name_end];
                 const option_value = option_contents[name_end + 1 ..];
                 if (try builder.addUserInputOption(option_name, option_value))
diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig
index 0ac556120885512572c9dde4a8525373849b8c72..10fc7b261c7925e55dee2211ac67139460847618 100644
--- a/lib/compiler/resinator/compile.zig
+++ b/lib/compiler/resinator/compile.zig
@@ -540,7 +540,7 @@ pub const Compiler = struct {
         //       This currently only checks for NUL bytes, but it should probably also check for
         //       platform-specific invalid characters like '*', '?', '"', '<', '>', '|' (Windows)
         //       Related: https://github.com/ziglang/zig/pull/14533#issuecomment-1416888193
-        if (std.mem.indexOfScalar(u8, filename_utf8, 0) != null) {
+        if (std.mem.findScalar(u8, filename_utf8, 0) != null) {
             return self.addErrorDetailsAndFail(.{
                 .err = .invalid_filename,
                 .token = node.filename.getFirstToken(),
@@ -2919,11 +2919,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void {
             var component_iterator = std.fs.path.componentIterator(path);
             while (component_iterator.next()) |component| {
                 // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
-                if (std.mem.indexOfAny(u8, component.name, "\x00<>:\"|?*") != null) return error.BadPathName;
+                if (std.mem.findAny(u8, component.name, "\x00<>:\"|?*") != null) return error.BadPathName;
             }
         },
         else => {
-            if (std.mem.indexOfScalar(u8, path, 0) != null) return error.BadPathName;
+            if (std.mem.findScalar(u8, path, 0) != null) return error.BadPathName;
         },
     }
 }
diff --git a/lib/compiler/resinator/cvtres.zig b/lib/compiler/resinator/cvtres.zig
index fb8ce8718907f1b369f4c5126e6d6f3bb554e85a..29d9e14ce8c0cfe4662d6f03cc4c67f8350da173 100644
--- a/lib/compiler/resinator/cvtres.zig
+++ b/lib/compiler/resinator/cvtres.zig
@@ -1056,7 +1056,7 @@ pub const supported_targets = struct {
         comptime {
             const info = @typeInfo(Arch).@"enum";
             for (info.field_names, info.field_values) |field_name, field_value| {
-                _ = std.mem.indexOfScalar(Arch, ordered_for_display, @fromBackingInt(@intCast(field_value))) orelse {
+                _ = std.mem.findScalar(Arch, ordered_for_display, @fromBackingInt(@intCast(field_value))) orelse {
                     @compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));
                 };
             }
diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig
index 3fda3d3c52724679a359e370ab8bee677100a45b..cbd5e5c74e31f33086db4ea446c6223ea5b07141 100644
--- a/lib/compiler/resinator/errors.zig
+++ b/lib/compiler/resinator/errors.zig
@@ -506,7 +506,7 @@ pub const ErrorDetails = struct {
                 // We know that the token slice is a well-formed #pragma code_page(N), so
                 // we can skip to the first ( and then get the number that follows
                 const token_slice = self.token.slice(source);
-                var number_start = std.mem.indexOfScalar(u8, token_slice, '(').? + 1;
+                var number_start = std.mem.findScalar(u8, token_slice, '(').? + 1;
                 while (std.ascii.isWhitespace(token_slice[number_start])) {
                     number_start += 1;
                 }
diff --git a/lib/compiler/resinator/source_mapping.zig b/lib/compiler/resinator/source_mapping.zig
index 8ae4a70dd0a4afef5c7f346a864693a9dfc799c5..d2f72821c2076d1794e734f741bc25b274595310 100644
--- a/lib/compiler/resinator/source_mapping.zig
+++ b/lib/compiler/resinator/source_mapping.zig
@@ -538,7 +538,7 @@ pub fn handleLineCommand(allocator: Allocator, line_command: []const u8, current
     defer allocator.free(filename);
 
     // \x00 bytes in the filename is incompatible with how StringTable works
-    if (std.mem.indexOfScalar(u8, filename, '\x00') != null) return error.InvalidLineCommand;
+    if (std.mem.findScalar(u8, filename, '\x00') != null) return error.InvalidLineCommand;
 
     current_mapping.line_num = linenum;
     current_mapping.filename.clearRetainingCapacity();
diff --git a/lib/docs/wasm/html_render.zig b/lib/docs/wasm/html_render.zig
index 5bb54f7ad2ba4a7ade1cb71f00b1a6ba037c26ef..cb94a016e44aff8d1b219d2f206a42109f635f17 100644
--- a/lib/docs/wasm/html_render.zig
+++ b/lib/docs/wasm/html_render.zig
@@ -62,7 +62,7 @@ pub fn fileSourceHtml(
     var cursor: usize = ast.tokenStart(start_token);
 
     var indent: usize = 0;
-    if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {
+    if (std.mem.findLast(u8, ast.source[0..cursor], "\n")) |newline_index| {
         for (ast.source[newline_index + 1 .. cursor]) |c| {
             if (c == ' ') {
                 indent += 1;
diff --git a/lib/docs/wasm/main.zig b/lib/docs/wasm/main.zig
index 7f8bf047e44235eabdc5350098923ca074e862bd..aba4d2ac4ff5568a9aa072291dc33869af0f1c63 100644
--- a/lib/docs/wasm/main.zig
+++ b/lib/docs/wasm/main.zig
@@ -153,11 +153,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
                 continue;
             }
             // substring, case insensitive match of full decl path
-            if (std.mem.indexOf(u8, g.full_path_search_text_lower.items, term) != null) {
+            if (std.mem.find(u8, g.full_path_search_text_lower.items, term) != null) {
                 points += 2;
                 continue;
             }
-            if (std.mem.indexOf(u8, g.doc_search_text.items, term) != null) {
+            if (std.mem.find(u8, g.doc_search_text.items, term) != null) {
                 points += 1;
                 continue;
             }
@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {
                 if (std.mem.endsWith(u8, tar_file.name, ".zig")) {
                     log.debug("found file: '{s}'", .{tar_file.name});
                     const file_name = try gpa.dupe(u8, tar_file.name);
-                    if (std.mem.indexOfScalar(u8, file_name, '/')) |pkg_name_end| {
+                    if (std.mem.findScalar(u8, file_name, '/')) |pkg_name_end| {
                         const pkg_name = file_name[0..pkg_name_end];
                         const gop = try Walk.modules.getOrPut(gpa, pkg_name);
                         const file: Walk.File.Index = @fromBackingInt(@intCast(Walk.files.entries.len));
diff --git a/lib/docs/wasm/markdown/Parser.zig b/lib/docs/wasm/markdown/Parser.zig
index 0b4695983cc7fc7dd89ffbd4273f809fdfe7bba1..3721b11b373b560de6617a4905b56fa106ae6d8e 100644
--- a/lib/docs/wasm/markdown/Parser.zig
+++ b/lib/docs/wasm/markdown/Parser.zig
@@ -159,7 +159,7 @@ const Block = struct {
             .heading => null,
             .code_block => code_block: {
                 const trimmed = mem.trimEnd(u8, unindented, " \t");
-                if (mem.indexOfNone(u8, trimmed, "`") != null or trimmed.len != b.data.code_block.fence_len) {
+                if (mem.findNone(u8, trimmed, "`") != null or trimmed.len != b.data.code_block.fence_len) {
                     const effective_indent = @min(indent, b.data.code_block.indent);
                     break :code_block line[effective_indent..];
                 } else {
@@ -594,7 +594,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart {
         };
     }
 
-    const number_end = mem.indexOfNone(u8, unindented_line, "0123456789") orelse return null;
+    const number_end = mem.findNone(u8, unindented_line, "0123456789") orelse return null;
     const after_number = unindented_line[number_end..];
     const marker: Block.Data.ListMarker = if (mem.startsWith(u8, after_number, ". "))
         .number_dot
@@ -639,10 +639,10 @@ fn startTableRow(unindented_line: []const u8) ?TableRowStart {
                 // Ignoring pipes in code spans allows table cells to contain
                 // code using ||, for example.
                 const open_start = i;
-                i = mem.indexOfNonePos(u8, table_row_content, i, "`") orelse return null;
+                i = mem.findNonePos(u8, table_row_content, i, "`") orelse return null;
                 const open_len = i - open_start;
-                while (mem.indexOfScalarPos(u8, table_row_content, i, '`')) |close_start| {
-                    i = mem.indexOfNonePos(u8, table_row_content, close_start, "`") orelse return null;
+                while (mem.findScalarPos(u8, table_row_content, i, '`')) |close_start| {
+                    i = mem.findNonePos(u8, table_row_content, close_start, "`") orelse return null;
                     const close_len = i - close_start;
                     if (close_len == open_len) break;
                 } else return null;
@@ -794,7 +794,7 @@ fn startCodeBlock(p: *Parser, unindented_line: []const u8) !?CodeBlockStart {
     } else "";
     // Code block tags may not contain backticks, since that would create
     // potential confusion with inline code spans.
-    if (fence_len < 3 or mem.indexOfScalar(u8, tag_bytes, '`') != null) return null;
+    if (fence_len < 3 or mem.findScalar(u8, tag_bytes, '`') != null) return null;
     return .{
         .tag = try p.addString(mem.trim(u8, tag_bytes, " ")),
         .fence_len = fence_len,
@@ -1382,12 +1382,12 @@ const InlineParser = struct {
     /// parsing.
     fn parseCodeSpan(ip: *InlineParser) !void {
         const opener_start = ip.pos;
-        ip.pos = mem.indexOfNonePos(u8, ip.content, ip.pos, "`") orelse ip.content.len;
+        ip.pos = mem.findNonePos(u8, ip.content, ip.pos, "`") orelse ip.content.len;
         const opener_len = ip.pos - opener_start;
 
         const start = ip.pos;
-        const end = while (mem.indexOfScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {
-            ip.pos = mem.indexOfNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;
+        const end = while (mem.findScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| {
+            ip.pos = mem.findNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len;
             const closer_len = ip.pos - closer_start;
 
             if (closer_len == opener_len) break closer_start;
@@ -1627,7 +1627,7 @@ fn addScratchStringLine(p: *Parser, line: []const u8) !void {
 }
 
 fn isBlank(line: []const u8) bool {
-    return mem.indexOfNone(u8, line, " \t") == null;
+    return mem.findNone(u8, line, " \t") == null;
 }
 
 fn isPunctuation(c: u8) bool {
diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig
index a6e1a65fbb6fcaba7313cea9503bfd06cc2fd4de..cf051dca8ec935688551a6da922634ae3e8320df 100644
--- a/lib/fuzzer.zig
+++ b/lib/fuzzer.zig
@@ -1085,7 +1085,7 @@ const Fuzzer = struct {
     fn removeBest(f: *Fuzzer, i: Input.Index, best_i: u32) void {
         const t = &f.tests[f.test_i];
         const ref = &t.corpus.items(.ref)[@backingInt(i)];
-        const list_i = mem.indexOfScalar(u32, ref.best_i_buf[0..ref.best_i_len], best_i).?;
+        const list_i = mem.findScalar(u32, ref.best_i_buf[0..ref.best_i_len], best_i).?;
         ref.best_i_len -= 1;
         ref.best_i_buf[list_i] = ref.best_i_buf[ref.best_i_len];
 
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 79b681e7404623d141293d7379d88c94f196f683..eed57a0b15b47b23b54b412c4305f12020b9773c 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -830,7 +830,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
         .kind = if (options.emit_object) .test_obj else .@"test",
         .root_module = options.root_module,
         .max_rss = options.max_rss,
-        .filters = b.dupeStrings(options.filters),
+        .filters = b.graph.dupeStrings(options.filters),
         .test_runner = options.test_runner,
         .use_llvm = options.use_llvm,
         .use_lld = options.use_lld,
@@ -2648,7 +2648,10 @@ pub const LazyPath = union(enum) {
 
     fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {
         return switch (lazy_path) {
-            .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
+            .src_path => |sp| .{ .src_path = .{
+                .owner = sp.owner,
+                .sub_path = sp.owner.graph.dupePath(sp.sub_path),
+            } },
             .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) },
             .relative => |r| .{ .relative = r },
             .generated => |gen| .{ .generated = .{
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index ccdb74499c7b41ed30b6f8b62953710e207d459b..5743d9800ced11e00ff61ce5a122c6c5bca83b3f 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -121,7 +121,7 @@ pub const Wip = struct {
         }
 
         pub fn hash(_: @This(), adapted_key: []const u8) u64 {
-            assert(std.mem.indexOfScalar(u8, adapted_key, 0) == null);
+            assert(std.mem.findScalar(u8, adapted_key, 0) == null);
             return std.hash_map.hashString(adapted_key);
         }
     };
@@ -182,7 +182,7 @@ pub const Wip = struct {
 
     pub fn addString(wip: *Wip, bytes: []const u8) Allocator.Error!String {
         const gpa = wip.gpa;
-        assert(std.mem.indexOfScalar(u8, bytes, 0) == null);
+        assert(std.mem.findScalar(u8, bytes, 0) == null);
         const gop = try wip.string_table.getOrPutContextAdapted(
             gpa,
             @as([]const u8, bytes),
@@ -439,7 +439,7 @@ pub const Wip = struct {
     /// Returned slice expires upon next append to the configuration.
     pub fn stringSlice(wip: *const Wip, s: String) [:0]const u8 {
         const start_slice = wip.string_bytes.items[@backingInt(s)..];
-        return start_slice[0..std.mem.indexOfScalar(u8, start_slice, 0).? :0];
+        return start_slice[0..std.mem.findScalar(u8, start_slice, 0).? :0];
     }
 };
 
@@ -1953,7 +1953,7 @@ pub const String = enum(u32) {
 
     pub fn slice(index: String, c: *const Configuration) [:0]const u8 {
         const start_slice = c.string_bytes[@backingInt(index)..];
-        return start_slice[0..std.mem.indexOfScalar(u8, start_slice, 0).? :0];
+        return start_slice[0..std.mem.findScalar(u8, start_slice, 0).? :0];
     }
 };
 
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index ac5dc3fd9330bee03bcbedce9a6c8d15d6df106c..7189ecd3e40c232b7a833a9d0bbb257835baab7a 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -402,8 +402,8 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
     const c_source_files = arena.create(CSourceFiles) catch @panic("OOM");
     c_source_files.* = .{
         .root = options.root orelse b.path(""),
-        .files = b.dupeStrings(options.files),
-        .flags = b.dupeStrings(options.flags),
+        .files = b.graph.dupeStrings(options.files),
+        .flags = b.graph.dupeStrings(options.flags),
         .language = options.language,
     };
     m.link_objects.append(arena, .{ .c_source_files = c_source_files }) catch @panic("OOM");
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 90d88f3a20785f3cb892b080212b8cda9afd5f88..0f7cdbc405d74778a28e370c477dcb5b58ca1e8c 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -375,7 +375,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
     const graph = owner.graph;
     const arena = graph.arena;
 
-    const name = owner.dupe(options.name);
+    const name = owner.graph.dupeString(options.name);
     if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {
         panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
     }
diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig
index 1cbbcbaef64a35185ab51a6cc17abc56b4d246af..e8595f3cbdbf24f5acfa642f3cd9ceb698a122c2 100644
--- a/lib/std/Io/Dispatch.zig
+++ b/lib/std/Io/Dispatch.zig
@@ -2782,7 +2782,7 @@ fn realPath(ev: *Evented, fd: c.fd_t, out_buffer: []u8) File.RealPathError!usize
             else => |err| return unexpectedErrno(err),
         }
     }
-    const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;
+    const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
     if (n > out_buffer.len) return error.NameTooLong;
     @memcpy(out_buffer[0..n], buffer[0..n]);
     return n;
@@ -2804,7 +2804,7 @@ fn dirRealPathFile(
         while (true) {
             if (c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
                 assert(redundant_pointer == out_buffer.ptr);
-                return std.mem.indexOfScalar(u8, out_buffer, 0) orelse out_buffer.len;
+                return std.mem.findScalar(u8, out_buffer, 0) orelse out_buffer.len;
             }
             const err: c.E = @fromBackingInt(@intCast(c._errno().*));
             switch (err) {
@@ -3792,7 +3792,7 @@ fn fileRealPath(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPa
             else => |err| return unexpectedErrno(err),
         }
     }
-    const n = std.mem.indexOfScalar(u8, &buffer, 0) orelse buffer.len;
+    const n = std.mem.findScalar(u8, &buffer, 0) orelse buffer.len;
     if (n > out_buffer.len) return error.NameTooLong;
     @memcpy(out_buffer[0..n], buffer[0..n]);
     return n;
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index c6473678a20326c606cabf29bd16e27af9ffd843..2c48909a6d169d8ed3ddc5cbc385f176a319864a 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -6836,7 +6836,7 @@ fn dirRealPathFilePosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, o
             if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| {
                 syscall.finish();
                 assert(redundant_pointer == out_buffer.ptr);
-                return std.mem.indexOfScalar(u8, out_buffer, 0) orelse out_buffer.len;
+                return std.mem.findScalar(u8, out_buffer, 0) orelse out_buffer.len;
             }
             const err: posix.E = @fromBackingInt(@intCast(std.c._errno().*));
             if (err == .INTR) {
@@ -6980,7 +6980,7 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {
                     },
                 }
             }
-            const n = std.mem.indexOfScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len;
+            const n = std.mem.findScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len;
             if (n > out_buffer.len) return error.NameTooLong;
             @memcpy(out_buffer[0..n], sufficient_buffer[0..n]);
             return n;
@@ -8999,7 +8999,7 @@ fn isCygwinPty(file: File) Io.Cancelable!bool {
     // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master
     return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or
         std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and
-        std.mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
+        std.mem.find(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
 }
 
 fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void {
@@ -16315,7 +16315,7 @@ fn windowsCreateProcessPathExt(
 
             const is_bat_or_cmd = bat_or_cmd: {
                 const app_name = app_buf.items[0..app_name_len];
-                const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :bat_or_cmd false;
+                const ext_start = std.mem.findScalarLast(u16, app_name, '.') orelse break :bat_or_cmd false;
                 const ext = app_name[ext_start..];
                 const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false;
                 switch (ext_enum) {
@@ -16351,7 +16351,7 @@ fn windowsCreateProcessPathExt(
                     // it's treated as an unrecoverable error. Otherwise, it'll be
                     // skipped as normal.
                     const app_name = app_buf.items[0..app_name_len];
-                    const ext_start = std.mem.lastIndexOfScalar(u16, app_name, '.') orelse break :unappended err;
+                    const ext_start = std.mem.findScalarLast(u16, app_name, '.') orelse break :unappended err;
                     const ext = app_name[ext_start..];
                     if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) {
                         return error.UnrecoverableInvalidExe;
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig
index 1dbb8cc043a7fc1354197a89a080af87e2789a48..6c4b1b2346e4cb955cecde24302bb4b15df4df18 100644
--- a/lib/std/Uri.zig
+++ b/lib/std/Uri.zig
@@ -221,16 +221,16 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
         }
 
         if (authority.len > start_of_host and authority[start_of_host] == '[') { // IPv6
-            end_of_host = std.mem.lastIndexOf(u8, authority, "]") orelse return error.InvalidFormat;
+            end_of_host = std.mem.findLast(u8, authority, "]") orelse return error.InvalidFormat;
             end_of_host += 1;
 
-            if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
+            if (std.mem.findLast(u8, authority, ":")) |index| {
                 if (index >= end_of_host) { // if not part of the V6 address field
                     end_of_host = @min(end_of_host, index);
                     uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
                 }
             }
-        } else if (std.mem.lastIndexOf(u8, authority, ":")) |index| {
+        } else if (std.mem.findLast(u8, authority, ":")) |index| {
             if (index >= start_of_host) { // if not part of the userinfo field
                 end_of_host = @min(end_of_host, index);
                 uri.port = std.fmt.parseInt(u16, authority[index + 1 ..], 10) catch return error.InvalidPort;
@@ -475,7 +475,7 @@ fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Co
     var aux: Writer = .fixed(aux_buf.*);
     if (!base.isEmpty()) {
         base.formatPath(&aux) catch return error.NoSpaceLeft;
-        aux.end = std.mem.lastIndexOfScalar(u8, aux.buffered(), '/') orelse return remove_dot_segments(new);
+        aux.end = std.mem.findScalarLast(u8, aux.buffered(), '/') orelse return remove_dot_segments(new);
     }
     aux.print("/{s}", .{new}) catch return error.NoSpaceLeft;
     const merged_path = remove_dot_segments(aux.buffered());
diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig
index fd2aa5ebc48b37c335465df7fe6ddf4a0623389b..b688551017f0cb945d67c0fb35d038ec332d7d78 100644
--- a/lib/std/array_hash_map.zig
+++ b/lib/std/array_hash_map.zig
@@ -13,12 +13,12 @@ const hash_map = @This();
 ///
 /// See `AutoContext` for a description of the hash and equal implementations.
 pub fn Auto(comptime K: type, comptime V: type) type {
-    return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));
+    return Custom(K, V, AutoContext(K), !autoEqlIsCheap(K));
 }
 
 /// An `ArrayHashMap` with strings as keys.
 pub fn String(comptime V: type) type {
-    return ArrayHashMap([]const u8, V, StringContext, true);
+    return Custom([]const u8, V, StringContext, true);
 }
 
 pub const StringContext = struct {
@@ -2130,7 +2130,7 @@ test "0 sized key and 0 sized value" {
 test "setKey storehash true" {
     const gpa = std.testing.allocator;
 
-    var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty;
+    var map: Custom(i32, i32, AutoContext(i32), true) = .empty;
     defer map.deinit(gpa);
 
     try map.put(gpa, 12, 34);
@@ -2146,7 +2146,7 @@ test "setKey storehash true" {
 test "setKey storehash false" {
     const gpa = std.testing.allocator;
 
-    var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty;
+    var map: Custom(i32, i32, AutoContext(i32), false) = .empty;
     defer map.deinit(gpa);
 
     try map.put(gpa, 12, 34);
@@ -2162,7 +2162,7 @@ test "setKey storehash false" {
 test "setKey storehash false with index" {
     const gpa = std.testing.allocator;
 
-    const T = ArrayHashMap(usize, usize, AutoContext(usize), false);
+    const T = Custom(usize, usize, AutoContext(usize), false);
 
     var map: T = .empty;
     defer map.deinit(gpa);
@@ -2180,9 +2180,9 @@ test "setKey storehash false with index" {
 test "setKey storehash true with index" {
     const gpa = std.testing.allocator;
 
-    const T = ArrayHashMap(usize, usize, AutoContext(usize), false);
+    const T = Custom(usize, usize, AutoContext(usize), false);
 
-    var map: ArrayHashMap(usize, usize, AutoContext(usize), true) = .empty;
+    var map: Custom(usize, usize, AutoContext(usize), true) = .empty;
     defer map.deinit(gpa);
 
     for (0..T.linear_scan_max + 1) |i| try map.put(gpa, i, i);
diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index f0d18e58a130cd18d0eb8c00dba3b6f32903c802..3bf35280d7a250a3bc029e8797da5da1ac97e92d 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -1148,9 +1148,9 @@ pub const rsa = struct {
             }
             var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
             var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];
-            std.mem.copyForwards(u8, m_p, @as(*const [8]u8, &@splat(0)));
-            std.mem.copyForwards(u8, m_p[8..], &mHash);
-            std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);
+            @memmove(m_p, @as(*const [8]u8, &@splat(0)));
+            @memmove(m_p[8..], &mHash);
+            @memmove(m_p[(8 + Hash.digest_length)..], salt);
 
             // 13.  Let H' = Hash(M'), an octet string of length hLen.
             var h_p: [Hash.digest_length]u8 = undefined;
diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig
index 7eede9c715f6121e9bff5151cb40fd59615f592d..ffba84b9e3f80c70fa9de109525bf8a3f3262ed2 100644
--- a/lib/std/fs/path.zig
+++ b/lib/std/fs/path.zig
@@ -1830,7 +1830,7 @@ fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []cons
 /// pointer address range of `path`, even if it is length zero.
 pub fn extension(path: []const u8) []const u8 {
     const filename = basename(path);
-    const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return path[path.len..];
+    const index = mem.findScalarLast(u8, filename, '.') orelse return path[path.len..];
     if (index == 0) return path[path.len..];
     return filename[index..];
 }
@@ -1887,7 +1887,7 @@ test extension {
 /// - "hello/world/lib"        ⇒ "lib"
 pub fn stem(path: []const u8) []const u8 {
     const filename = basename(path);
-    const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return filename[0..];
+    const index = mem.findScalarLast(u8, filename, '.') orelse return filename[0..];
     if (index == 0) return path;
     return filename[0..index];
 }
diff --git a/lib/std/heap/SafeAllocator.zig b/lib/std/heap/SafeAllocator.zig
index 41199df8aa39d526938dc72a2ceccd80168c3dc0..91f65184241713f66a39953092d889cd2bed4b84 100644
--- a/lib/std/heap/SafeAllocator.zig
+++ b/lib/std/heap/SafeAllocator.zig
@@ -1519,7 +1519,7 @@ const FuzzSingleThreadedAllocator = struct {
         @disableInstrumentation();
 
         const allocs_slice = f.allocs.slice();
-        const i = mem.indexOfScalar([*]u8, allocs_slice.items(.ptr), memory.ptr) orelse panic(
+        const i = mem.findScalar([*]u8, allocs_slice.items(.ptr), memory.ptr) orelse panic(
             "invalid SafeAllocator free of {f}",
             .{FormatMemory{ .memory = memory, .alignment = alignment }},
         );
diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig
index 6523fa672f005664296726a858d40b3935b5561f..c505605c03406e3ef760fabe031175358a207cd5 100644
--- a/lib/std/http/Server.zig
+++ b/lib/std/http/Server.zig
@@ -102,7 +102,7 @@ pub const Request = struct {
             const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse
                 return error.UnknownHttpMethod;
 
-            const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse
+            const version_start = mem.findScalarLast(u8, first_line, ' ') orelse
                 return error.HttpHeadersInvalid;
             if (version_start == method_end) return error.HttpHeadersInvalid;
 
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 2d0d5f7d8bbb5653dbdaf55ee95c2cf85fa47b5e..55b9019c4f4d95cfce0f271de52d12a856f9aea8 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -1528,7 +1528,7 @@ pub fn findLast(comptime T: type, haystack: []const T, needle: []const T) ?usize
     if (needle.len == 0) return haystack.len;
 
     if (!std.meta.hasUniqueRepresentation(T) or haystack.len < 52 or needle.len <= 4)
-        return lastIndexOfLinear(T, haystack, needle);
+        return findLastLinear(T, haystack, needle);
 
     const haystack_bytes = sliceAsBytes(haystack);
     const needle_bytes = sliceAsBytes(needle);
@@ -1583,26 +1583,26 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle
 
 test find {
     try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
-    try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
+    try testing.expect(findLast(u8, "one two three four five six seven eight nine ten eleven", "three four").? == 8);
     try testing.expect(find(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
-    try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
+    try testing.expect(findLast(u8, "one two three four five six seven eight nine ten eleven", "two two") == null);
 
     try testing.expect(find(u8, "one two three four five six seven eight nine ten", "").? == 0);
-    try testing.expect(lastIndexOf(u8, "one two three four five six seven eight nine ten", "").? == 48);
+    try testing.expect(findLast(u8, "one two three four five six seven eight nine ten", "").? == 48);
 
     try testing.expect(find(u8, "one two three four", "four").? == 14);
-    try testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14);
+    try testing.expect(findLast(u8, "one two three two four", "two").? == 14);
     try testing.expect(find(u8, "one two three four", "gour") == null);
-    try testing.expect(lastIndexOf(u8, "one two three four", "gour") == null);
+    try testing.expect(findLast(u8, "one two three four", "gour") == null);
     try testing.expect(find(u8, "foo", "foo").? == 0);
-    try testing.expect(lastIndexOf(u8, "foo", "foo").? == 0);
+    try testing.expect(findLast(u8, "foo", "foo").? == 0);
     try testing.expect(find(u8, "foo", "fool") == null);
-    try testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);
-    try testing.expect(lastIndexOf(u8, "foo", "fool") == null);
+    try testing.expect(findLast(u8, "foo", "lfoo") == null);
+    try testing.expect(findLast(u8, "foo", "fool") == null);
 
     try testing.expect(find(u8, "foo foo", "foo").? == 0);
-    try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
-    try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
+    try testing.expect(findLast(u8, "foo foo", "foo").? == 4);
+    try testing.expect(findLastAny(u8, "boo, cat", "abo").? == 6);
     try testing.expect(findScalarLast(u8, "boo", 'o').? == 2);
 }
 
@@ -1624,13 +1624,13 @@ test "find multibyte" {
         // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm
         const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ @as([100]u16, @splat(0));
         const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee };
-        try testing.expectEqual(lastIndexOf(u16, &haystack, &needle), 0);
+        try testing.expectEqual(findLast(u16, &haystack, &needle), 0);
 
         // check for misaligned false positives (little and big endian)
         const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff };
-        try testing.expectEqual(lastIndexOf(u16, &haystack, &needleLE), null);
+        try testing.expectEqual(findLast(u16, &haystack, &needleLE), null);
         const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 };
-        try testing.expectEqual(lastIndexOf(u16, &haystack, &needleBE), null);
+        try testing.expectEqual(findLast(u16, &haystack, &needleBE), null);
     }
 }
 
@@ -3485,8 +3485,8 @@ pub fn SplitBackwardsIterator(comptime T: type, comptime delimiter_type: Delimit
         pub fn next(self: *Self) ?[]const T {
             const end = self.index orelse return null;
             const start = if (switch (delimiter_type) {
-                .sequence => lastIndexOf(T, self.buffer[0..end], self.delimiter),
-                .any => lastIndexOfAny(T, self.buffer[0..end], self.delimiter),
+                .sequence => findLast(T, self.buffer[0..end], self.delimiter),
+                .any => findLastAny(T, self.buffer[0..end], self.delimiter),
                 .scalar => findScalarLast(T, self.buffer[0..end], self.delimiter),
             }) |delim_start| blk: {
                 self.index = delim_start;
diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig
index 891ce5a397f61e2b6c655192d714e35d21f7e32c..070bd4245f12cdcc48723e5db51ac72d5d74f2bf 100644
--- a/lib/std/os/linux/IoUring/test.zig
+++ b/lib/std/os/linux/IoUring/test.zig
@@ -2699,7 +2699,7 @@ inline fn skipKernelLessThan(required: std.SemanticVersion) !void {
 
     const release = mem.sliceTo(&uts.release, 0);
     // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64"
-    const extra_index = std.mem.indexOfAny(u8, release, "-+");
+    const extra_index = std.mem.findAny(u8, release, "-+");
     const stripped = release[0..(extra_index orelse release.len)];
     // Make sure the input don't rely on the extra we just stripped
     try testing.expect(required.pre == null and required.build == null);
diff --git a/lib/std/tar/Writer.zig b/lib/std/tar/Writer.zig
index 85941c967fcd831bc725480d715ce9d946f363a1..d43c8962d8205c35648855dbc1e6cc4bbd893edb 100644
--- a/lib/std/tar/Writer.zig
+++ b/lib/std/tar/Writer.zig
@@ -312,7 +312,7 @@ pub const Header = extern struct {
 
         // add as much to prefix as you can, must split at /
         const prefix_remaining = max_prefix - prefix_pos;
-        if (std.mem.lastIndexOf(u8, sub_path[0..@min(prefix_remaining, sub_path.len)], &.{'/'})) |sep_pos| {
+        if (std.mem.findLast(u8, sub_path[0..@min(prefix_remaining, sub_path.len)], &.{'/'})) |sep_pos| {
             @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]);
             if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong;
             @memcpy(w.name[0..][0 .. sub_path.len - sep_pos - 1], sub_path[sep_pos + 1 ..]);
diff --git a/lib/std/tar/test.zig b/lib/std/tar/test.zig
index e01fd4b884dd4b0cff328238b60288bc2a535d87..fa66d51cedb7730012d1b432c90f8d98928610c0 100644
--- a/lib/std/tar/test.zig
+++ b/lib/std/tar/test.zig
@@ -474,14 +474,14 @@ test "should not overwrite existing file" {
     defer root.cleanup();
     try testing.expectError(
         error.PathAlreadyExists,
-        tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }),
+        tar.extract(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }),
     );
 
     // Unpack with strip_components = 0 should pass
     r = .fixed(data);
     var root2 = std.testing.tmpDir(.{});
     defer root2.cleanup();
-    try tar.pipeToFileSystem(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 });
+    try tar.extract(io, root2.dir, &r, .{ .mode_mode = .ignore, .strip_components = 0 });
 }
 
 test "case sensitivity" {
@@ -501,7 +501,7 @@ test "case sensitivity" {
     var root = std.testing.tmpDir(.{});
     defer root.cleanup();
 
-    tar.pipeToFileSystem(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
+    tar.extract(io, root.dir, &r, .{ .mode_mode = .ignore, .strip_components = 1 }) catch |err| {
         // on case insensitive fs we fail on overwrite existing file
         try testing.expectEqual(error.PathAlreadyExists, err);
         return;
diff --git a/lib/std/testing.zig b/lib/std/testing.zig
index 46c7fe938b22300c23dcedc3570cb329090d3d3a..eebf3a5195c0d2407c7c51d3b67ef794011f6736 100644
--- a/lib/std/testing.zig
+++ b/lib/std/testing.zig
@@ -999,7 +999,7 @@ test "expectEqualDeep composite type" {
 }
 
 fn printIndicatorLine(source: []const u8, indicator_index: usize) void {
-    const line_begin_index = if (std.mem.lastIndexOfScalar(u8, source[0..indicator_index], '\n')) |line_begin|
+    const line_begin_index = if (std.mem.findScalarLast(u8, source[0..indicator_index], '\n')) |line_begin|
         line_begin + 1
     else
         0;
diff --git a/lib/std/testing/Smith.zig b/lib/std/testing/Smith.zig
index a60a9802391078fe6ca400fb4409216bd73ff345..39da2910c5657b62ac6bac5103bca1e286a63cf7 100644
--- a/lib/std/testing/Smith.zig
+++ b/lib/std/testing/Smith.zig
@@ -52,7 +52,7 @@ pub inline fn baselineWeights(T: type) []const Weight {
         .bool, .int, .float => i: {
             // Reject types that don't have a fixed bitsize (esp. usize)
             // since they are not gauraunteed to fit in a u64 across targets.
-            if (std.mem.indexOfScalar(type, &.{
+            if (std.mem.findScalar(type, &.{
                 isize,      usize,
                 c_char,     c_longdouble,
                 c_short,    c_ushort,
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
index 4a5232f27b506faa9205badfb2ef194e96583e64..332e0114b02c3cf9747c0d3bba2021eb1b15befd 100644
--- a/lib/std/zig.zig
+++ b/lib/std/zig.zig
@@ -1560,7 +1560,7 @@ pub fn resolvePath(
     // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.
     for (paths) |p| {
         if (Dir.path.isAbsolute(p)) break; // absolute path
-        if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir
+        if (mem.find(u8, p, "..") != null) break; // may contain up-dir
     } else {
         // no absolute path, no "..".
         const res = try Dir.path.resolve(gpa, paths);
diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig
index 53d9027d1351ebcd4a5658f6d3702bfe22cc95ca..ddbaea460f5f37dd9885bf00db51c1d62d827ff2 100644
--- a/lib/std/zig/Ast/Render.zig
+++ b/lib/std/zig/Ast/Render.zig
@@ -941,20 +941,20 @@ fn renderExpressionFixup(r: *Render, node: Ast.Node.Index, space: Space) Error!v
 }
 
 fn drainNoNewline(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
-    if (std.mem.indexOfScalar(u8, w.buffered(), '\n') != null) {
+    if (std.mem.findScalar(u8, w.buffered(), '\n') != null) {
         return error.WriteFailed;
     }
 
     var n: usize = 0;
     for (data[0 .. data.len - 1]) |v| {
-        if (std.mem.indexOfScalar(u8, v, '\n') != null) {
+        if (std.mem.findScalar(u8, v, '\n') != null) {
             return error.WriteFailed;
         }
         n += v.len;
     }
 
     const pattern = data[data.len - 1];
-    if (splat != 0 and std.mem.indexOfScalar(u8, pattern, '\n') != null) {
+    if (splat != 0 and std.mem.findScalar(u8, pattern, '\n') != null) {
         return error.WriteFailed;
     }
     n += pattern.len * splat;
@@ -990,7 +990,7 @@ fn rendersMultiline(r: *const Render, node: Ast.Node.Index) error{OutOfMemory}!b
         error.WriteFailed => return true,
     };
     if (sub_ais.disabled_offset != null) return true;
-    if (std.mem.indexOfScalar(u8, no_nl_w.buffered(), '\n') != null) {
+    if (std.mem.findScalar(u8, no_nl_w.buffered(), '\n') != null) {
         return true;
     }
 
@@ -2993,7 +2993,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
 /// Returns true if there exists a doc comment between the start
 /// of token `start_token` and the start of token `end_token`.
 fn hasDocComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
-    return std.mem.indexOfScalar(
+    return std.mem.findScalar(
         Token.Tag,
         tree.tokens.items(.tag)[start_token..end_token],
         .doc_comment,
diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig
index 9016796a73b0f98f2ded17ef132ea9b4466140ca..890ead68aa27a8c0f7f6cd75b97c822f1e8e77c0 100644
--- a/lib/std/zig/llvm/Builder.zig
+++ b/lib/std/zig/llvm/Builder.zig
@@ -9919,7 +9919,7 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr
 pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes {
     try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1);
     const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast(
-        fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last|
+        fn_attributes[0..if (std.mem.findLastNone(Attributes, fn_attributes, &.{.none})) |last|
             last + 1
         else
             0],
diff --git a/lib/std/zip.zig b/lib/std/zip.zig
index a42a9f395c694c7df04d78e7ca63baafae3b6cfd..1434702ffbf62f3db7fd1b0c133d1af501365133 100644
--- a/lib/std/zip.zig
+++ b/lib/std/zip.zig
@@ -109,7 +109,7 @@ pub const EndRecord = extern struct {
 
     /// TODO audit this logic
     pub fn findBuffer(buffer: []const u8) FindBufferError!EndRecord {
-        const pos = std.mem.lastIndexOf(u8, buffer, &end_record_sig) orelse return error.ZipNoEndRecord;
+        const pos = std.mem.findLast(u8, buffer, &end_record_sig) orelse return error.ZipNoEndRecord;
         if (pos + @sizeOf(EndRecord) > buffer.len) return error.EndOfStream;
         const record_ptr: *EndRecord = @ptrCast(buffer[pos..][0..@sizeOf(EndRecord)]);
         var record = record_ptr.*;
diff --git a/src/Air.zig b/src/Air.zig
index fbaa370132a6044191d71a7b68d79915584fd979..ad4526f0760417f5b90819864a73c62e7f6c00a3 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -1907,7 +1907,7 @@ pub const NullTerminatedString = enum(u32) {
     pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {
         if (nts == .none) return "";
         const bytes = std.mem.sliceAsBytes(air.extra.items[@backingInt(nts)..]);
-        return bytes[0..std.mem.indexOfScalar(u8, bytes, 0).? :0];
+        return bytes[0..std.mem.findScalar(u8, bytes, 0).? :0];
     }
 };
 
diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig
index 20c1af1969ad117ee63acd6428f1ee0c8490f6e6..cbbe07ba3d212b5e485159e089d90c2d6f9a75ef 100644
--- a/src/IncrementalDebugServer.zig
+++ b/src/IncrementalDebugServer.zig
@@ -130,7 +130,7 @@ fn serveStream(
         try stream_writer.writeAll("zig> ");
         const untrimmed = try stream_reader.takeSentinel('\n');
         const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n");
-        const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i|
+        const cmd: []const u8, const arg: []const u8 = if (std.mem.findScalar(u8, cmd_and_arg, ' ')) |i|
             .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }
         else
             .{ cmd_and_arg, "" };
@@ -244,7 +244,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
             const ty: Type = .fromInterned(type_ip_index);
             const ty_name = ty.containerTypeName(ip).toSlice(ip);
             const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {
-                0b00 => std.mem.indexOf(u8, ty_name, query) != null,
+                0b00 => std.mem.find(u8, ty_name, query) != null,
                 0b01 => std.mem.endsWith(u8, ty_name, query),
                 0b10 => std.mem.startsWith(u8, ty_name, query),
                 0b11 => std.mem.eql(u8, ty_name, query),
@@ -265,7 +265,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
             const nav = ip.getNav(nav_index);
             const nav_fqn = nav.fqn.toSlice(ip);
             const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) {
-                0b00 => std.mem.indexOf(u8, nav_fqn, query) != null,
+                0b00 => std.mem.find(u8, nav_fqn, query) != null,
                 0b01 => std.mem.endsWith(u8, nav_fqn, query),
                 0b10 => std.mem.startsWith(u8, nav_fqn, query),
                 0b11 => std.mem.eql(u8, nav_fqn, query),
@@ -378,7 +378,7 @@ fn parseIndex(str: []const u8) ?u32 {
     return std.fmt.parseInt(u32, str, 10) catch null;
 }
 fn parseAnalUnit(str: []const u8) ?AnalUnit {
-    const split_idx = std.mem.indexOfScalar(u8, str, ' ') orelse return null;
+    const split_idx = std.mem.findScalar(u8, str, ' ') orelse return null;
     const kind = str[0..split_idx];
     const idx_str = str[split_idx + 1 ..];
     if (std.mem.eql(u8, kind, "comptime")) {
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 8502055c372f2fb915be32133ee6a8be60916e4b..a5c3bdd044920a3fa745249467879385ed20fbec 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -1737,7 +1737,7 @@ pub const String = enum(u32) {
     }
 
     pub fn toNullTerminatedString(string: String, len: u64, ip: *const InternPool) NullTerminatedString {
-        assert(std.mem.indexOfScalar(u8, string.toSlice(len, ip), 0) == null);
+        assert(std.mem.findScalar(u8, string.toSlice(len, ip), 0) == null);
         assert(string.at(len, ip) == 0);
         return @fromBackingInt(@intCast(@backingInt(string)));
     }
@@ -1864,7 +1864,7 @@ pub const NullTerminatedString = enum(u32) {
     pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 {
         const slice = string.toSlice(ip);
         if (slice.len > 1 and slice[0] == '0') return null;
-        if (std.mem.indexOfScalar(u8, slice, '_')) |_| return null;
+        if (std.mem.findScalar(u8, slice, '_')) |_| return null;
         return std.fmt.parseUnsigned(u32, slice, 10) catch null;
     }
 
@@ -11428,7 +11428,7 @@ pub fn getOrPutTrailingString(
         .tid = tid,
         .index = strings.mutate.len - 1,
     }).wrap(ip))));
-    const has_embedded_null = std.mem.indexOfScalar(u8, key, 0) != null;
+    const has_embedded_null = std.mem.findScalar(u8, key, 0) != null;
     switch (embedded_nulls) {
         .no_embedded_nulls => assert(!has_embedded_null),
         .maybe_embedded_nulls => if (has_embedded_null) {
diff --git a/src/Sema.zig b/src/Sema.zig
index b2bdfc6abf88324c01e74d78dae9473c5143ac8e..c7d40ffa095a3416a65806bba49d84f6bbbc8da7 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -34856,7 +34856,7 @@ pub fn resolveNavPtrModifiers(
         const linksection_body = zir_decl.linksection_body orelse break :ls .none;
         const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst);
         const bytes = try sema.toConstString(block, section_src, linksection_ref, .{ .simple = .@"linksection" });
-        if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
+        if (std.mem.findScalar(u8, bytes, 0) != null) {
             return sema.fail(block, section_src, "linksection cannot contain null bytes", .{});
         } else if (bytes.len == 0) {
             return sema.fail(block, section_src, "linksection cannot be empty", .{});
diff --git a/src/Value.zig b/src/Value.zig
index f6905eb4b55d11df4c1610c9c8e41475cd4fe522..a5b685c7913117befb984dfb85dd5d7f081e5721 100644
--- a/src/Value.zig
+++ b/src/Value.zig
@@ -954,7 +954,7 @@ pub fn anyScalarIsZero(val: Value, zcu: *Zcu) bool {
                 .bytes => |str| {
                     const len = Type.fromInterned(agg.ty).vectorLen(zcu);
                     const slice = str.toSlice(len, &zcu.intern_pool);
-                    return std.mem.indexOfScalar(u8, slice, 0) != null;
+                    return std.mem.findScalar(u8, slice, 0) != null;
                 },
                 .elems => |elems| {
                     for (elems) |elem| {
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 92659d3253b60fb26eddac3eadf3ce9ec6ba1499..5f64440990c95be60453ee38c1dde3d2850a058f 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -652,7 +652,7 @@ pub const StdLangDecl = enum {
         return switch (decl) {
             inline else => |tag| {
                 const name = @tagName(tag);
-                const split = (comptime std.mem.lastIndexOfScalar(u8, name, '.')) orelse return .{ .direct = name };
+                const split = (comptime std.mem.findScalarLast(u8, name, '.')) orelse return .{ .direct = name };
                 const parent = @field(StdLangDecl, name[0..split]);
                 comptime assert(@backingInt(parent) < @backingInt(tag)); // dependencies ordered correctly
                 return .{ .nested = .{ parent, name[split + 1 ..] } };
@@ -4299,7 +4299,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana
                         const fqn_slice = nav.fqn.toSlice(ip);
                         if (comp.test_filters.len > 0) {
                             for (comp.test_filters) |test_filter| {
-                                if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
+                                if (std.mem.find(u8, fqn_slice, test_filter) != null) break;
                             } else break :a false;
                         }
                         break :a true;
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index bf72a73851b39910c3d43250a286efa98f780b20..64240f77c1c721bfcf90be0def4bb92aa7b07e99 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -3176,7 +3176,7 @@ const ScanDeclIter = struct {
                 if (is_named and comp.test_filters.len > 0) {
                     const fqn_slice = fqn.toSlice(ip);
                     for (comp.test_filters) |test_filter| {
-                        if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
+                        if (std.mem.find(u8, fqn_slice, test_filter) != null) break;
                     } else break :a false;
                 }
                 try zcu.test_functions.put(gpa, nav, {});
diff --git a/src/codegen/aarch64/Assemble.zig b/src/codegen/aarch64/Assemble.zig
index 2875f6fc960e211f684d37815ba86de291fd8453..2d5cc913270f0259caa726e4073b34e1992fef8f 100644
--- a/src/codegen/aarch64/Assemble.zig
+++ b/src/codegen/aarch64/Assemble.zig
@@ -163,7 +163,7 @@ const matchers = matchers: {
                         arg.* = zonCast(param_type.?, instruction.encode[encode_index], symbols);
                     return @call(.auto, encode, args);
                 } else if (pattern_token[0] == '<') {
-                    const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
+                    const symbol_name = comptime pattern_token[1 .. std.mem.findScalarPos(u8, pattern_token, 1, '|') orelse
                         pattern_token.len - 1];
                     const symbol = @field(Symbol, symbol_name);
                     const symbol_ptr = &@field(symbols, symbol_name);
diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
index 1050b8fb0eb1425205f04b7440640ec55d6cf69a..520bad02743a1a0537226e7f40a6595046a3a42b 100644
--- a/src/codegen/aarch64/Select.zig
+++ b/src/codegen/aarch64/Select.zig
@@ -2856,7 +2856,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
                     const remaining_source = std.mem.span(as.source);
                     return isel.fail("unable to assemble: '{s}'", .{std.mem.trim(
                         u8,
-                        as.source[0 .. std.mem.indexOfScalar(u8, remaining_source, '\n') orelse remaining_source.len],
+                        as.source[0 .. std.mem.findScalar(u8, remaining_source, '\n') orelse remaining_source.len],
                         &std.ascii.whitespace,
                     )});
                 },
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 5ab86a9a5fad9e1a4391053bd5e1af970de1feeb..f2c8431dcab682067b18a9c785e1ac2edda4ade5 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -5013,7 +5013,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
         while (it.next()) |input| {
             const constraint = input.constraint;
 
-            if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
+            if (constraint.len < 1 or mem.findScalar(u8, "=+&%", constraint[0]) != null or
                 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
             {
                 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
@@ -5077,7 +5077,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
                 }
 
                 const desc = mem.sliceTo(asm_source[src_i..], ']');
-                if (mem.indexOfScalar(u8, desc, ':')) |colon| {
+                if (mem.findScalar(u8, desc, ':')) |colon| {
                     const name = desc[0..colon];
                     const modifier = desc[colon + 1 ..];
 
diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig
index aed925be2953ddfb56581b9bb5eef521e8b78507..1a6ae84190bf394992f5e30b305de583be9b5829 100644
--- a/src/codegen/riscv64/CodeGen.zig
+++ b/src/codegen/riscv64/CodeGen.zig
@@ -6235,8 +6235,8 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
         next_op: for (&ops) |*op| {
             const op_str = while (!last_op) {
                 const full_str = op_it.next() orelse break :next_op;
-                const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse
-                    mem.indexOf(u8, full_str, "//")) |comment|
+                const code_str = if (mem.findScalar(u8, full_str, '#') orelse
+                    mem.find(u8, full_str, "//")) |comment|
                 code: {
                     last_op = true;
                     break :code full_str[0..comment];
@@ -6250,7 +6250,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
             } else if (std.fmt.parseInt(i12, op_str, 10)) |int| {
                 op.* = .{ .imm = Immediate.s(int) };
             } else |_| if (mem.startsWith(u8, op_str, "%[")) {
-                const mod_index = mem.indexOf(u8, op_str, "]@");
+                const mod_index = mem.find(u8, op_str, "]@");
                 const modifier = if (mod_index) |index|
                     op_str[index + "]@".len ..]
                 else
diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig
index 4958d17e304cb7cccc3e4b383bd46e1d09141c0a..095de8590a768c68a010bb375f07cf0206c83a10 100644
--- a/src/codegen/x86_64/CodeGen.zig
+++ b/src/codegen/x86_64/CodeGen.zig
@@ -177899,7 +177899,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
         else if (std.mem.endsWith(u8, mnem_str, "l"))
             .dword
         else if (std.mem.endsWith(u8, mnem_str, "q") and
-            (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or
+            (std.mem.findScalar(u8, "vp", mnem_str[0]) == null or
                 !std.mem.endsWith(u8, mnem_str, "dq")))
             .qword
         else if (std.mem.endsWith(u8, mnem_str, "t"))
@@ -177966,8 +177966,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
                         }) + 1,
                     }
                 };
-                const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse
-                    std.mem.indexOf(u8, full_op_str, "//")) |comment|
+                const untrimmed_op_str = if (std.mem.findScalar(u8, full_op_str, '#') orelse
+                    std.mem.find(u8, full_op_str, "//")) |comment|
                 untrimmed_op_str: {
                     ops_index = ops_str.len;
                     break :untrimmed_op_str full_op_str[0..comment];
@@ -177976,7 +177976,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
                 if (trimmed_op_str.len > 0) break trimmed_op_str;
             };
             if (std.mem.startsWith(u8, op_str, "%%")) {
-                const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
+                const colon = std.mem.findScalarPos(u8, op_str, "%%".len + 2, ':');
                 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
                     return self.fail("invalid register: '{s}'", .{op_str});
                 if (colon) |colon_pos| {
@@ -177997,7 +177997,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
                     op.* = .{ .reg = reg };
                 }
             } else if (std.mem.startsWith(u8, op_str, "%[") and std.mem.endsWith(u8, op_str, "]")) {
-                const colon = std.mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
+                const colon = std.mem.findScalarPos(u8, op_str, "%[".len, ':');
                 const modifier = if (colon) |colon_pos|
                     op_str[colon_pos + ":".len .. op_str.len - "]".len]
                 else
@@ -178080,7 +178080,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
                 else |_|
                     return self.fail("invalid immediate: '{s}'", .{op_str});
             } else if (std.mem.endsWith(u8, op_str, ")")) {
-                const open = std.mem.indexOfScalar(u8, op_str, '(') orelse
+                const open = std.mem.findScalar(u8, op_str, '(') orelse
                     return self.fail("invalid operand: '{s}'", .{op_str});
                 var sib_it =
                     std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
@@ -178141,7 +178141,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
                         .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and
                             std.mem.endsWith(u8, op_str[0..open], "]"))
                         disp: {
-                            const colon = std.mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
+                            const colon = std.mem.findScalarPos(u8, op_str[0..open], "%[".len, ':');
                             const modifier = if (colon) |colon_pos|
                                 op_str[colon_pos + ":".len .. open - "]".len]
                             else
@@ -178210,14 +178210,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
             .{ ._, .pseudo }
         else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
             const fixes_name = @tagName(fixes);
-            const space_index = std.mem.indexOfScalar(u8, fixes_name, ' ');
+            const space_index = std.mem.findScalar(u8, fixes_name, ' ');
             const fixes_prefix = if (space_index) |index|
                 std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..index]).?
             else
                 .none;
             if (fixes_prefix != prefix) continue;
             const pattern = fixes_name[if (space_index) |index| index + " ".len else 0..];
-            const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
+            const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
             const mnem_prefix = pattern[0..wildcard_index];
             const mnem_suffix = pattern[wildcard_index + "_".len ..];
             if (!std.mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
@@ -178463,11 +178463,11 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
         .sse => switch (ty.zigTypeTag(zcu)) {
             else => {
                 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target, .other), .none);
-                assert(std.mem.indexOfNone(abi.Class, classes, &.{
+                assert(std.mem.findNone(abi.Class, classes, &.{
                     .integer, .sse, .sseup, .memory, .float, .float_combine,
                 }) == null);
                 const abi_size = ty.abiSize(zcu);
-                if (abi_size < 4 or std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
+                if (abi_size < 4 or std.mem.findScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
                     1 => return if (cg.hasFeature(.avx)) .{ .vex_insert_extract = .{
                         .insert = .{ .vp_b, .insr },
                         .extract = .{ .vp_b, .extr },
@@ -183578,8 +183578,8 @@ const Temp = struct {
             const class = classes[class_index];
             next_class_index = @intCast(switch (class) {
                 .integer, .memory, .float, .float_combine => class_index + 1,
-                .sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
-                .x87 => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
+                .sse => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
+                .x87 => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
                 .sseup,
                 .x87up,
                 .none,
@@ -189825,7 +189825,7 @@ const Select = struct {
             s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) {
                 error.InvalidInstruction => {
                     const fixes = @tagName(mir_tag[0]);
-                    const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
+                    const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
                     return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{
                         fixes[0..fixes_blank],
                         @tagName(mir_tag[1]),
@@ -189905,7 +189905,7 @@ const Select = struct {
                 .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
                 else => {
                     const fixes = @tagName(mir_tag[0]);
-                    const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
+                    const fixes_blank = std.mem.findScalar(u8, fixes, '_').?;
                     std.debug.panic("{s}: {s}{s}{s}\n", .{
                         @src().fn_name,
                         fixes[0..fixes_blank],
diff --git a/src/codegen/x86_64/Lower.zig b/src/codegen/x86_64/Lower.zig
index f471d990d1f19bd10d120d2d69f53266ab5538d3..389d57f62d6540f7f5dc096d65c59402f72ab06b 100644
--- a/src/codegen/x86_64/Lower.zig
+++ b/src/codegen/x86_64/Lower.zig
@@ -435,11 +435,11 @@ const mnemonic_table: [inst_tags_len * inst_fixes_len]?Mnemonic = table: {
     for (0..inst_fixes_len) |fixes_i| {
         const fixes: Mir.Inst.Fixes = @fromBackingInt(@intCast(fixes_i));
         const prefix, const suffix = affix: {
-            const pattern = if (std.mem.indexOfScalar(u8, @tagName(fixes), ' ')) |i|
+            const pattern = if (std.mem.findScalar(u8, @tagName(fixes), ' ')) |i|
                 @tagName(fixes)[i + 1 ..]
             else
                 @tagName(fixes);
-            const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?;
+            const wildcard_idx = std.mem.findScalar(u8, pattern, '_').?;
             break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] };
         };
         for (0..inst_tags_len) |inst_tag_i| {
@@ -477,7 +477,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
         else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
     };
     try lower.encode(switch (fixes) {
-        inline else => |tag| comptime if (std.mem.indexOfScalar(u8, @tagName(tag), ' ')) |space|
+        inline else => |tag| comptime if (std.mem.findScalar(u8, @tagName(tag), ' ')) |space|
             @field(Prefix, @tagName(tag)[0..space])
         else
             .none,
@@ -487,8 +487,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
         }
         // 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 pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..];
+        const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
         return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{
             pattern[0..wildcard_index],
             @tagName(inst.tag),
diff --git a/src/codegen/x86_64/Mir.zig b/src/codegen/x86_64/Mir.zig
index 90fbbdf3125b2e449dc9723a0b98ce26a6b228c2..274437d54ccf55ce4fb47470e7a82b607c4bf0d2 100644
--- a/src/codegen/x86_64/Mir.zig
+++ b/src/codegen/x86_64/Mir.zig
@@ -1745,8 +1745,8 @@ pub const Inst = struct {
             for (@typeInfo(Mnemonic).@"enum".field_names) |mnemonic_name| {
                 if (mnemonic_name[0] == '.') continue;
                 for (@typeInfo(Fixes).@"enum".field_names) |fixes_name| {
-                    const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..];
-                    const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?;
+                    const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..];
+                    const wildcard_index = std.mem.findScalar(u8, pattern, '_').?;
                     const mnem_prefix = pattern[0..wildcard_index];
                     const mnem_suffix = pattern[wildcard_index + "_".len ..];
                     if (!std.mem.startsWith(u8, mnemonic_name, mnem_prefix)) continue;
@@ -1823,7 +1823,7 @@ pub const NullTerminatedString = enum(u32) {
     pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 {
         if (nts == .none) return null;
         const string_bytes = mir.string_bytes[@backingInt(nts)..];
-        return string_bytes[0..std.mem.indexOfScalar(u8, string_bytes, 0).? :0];
+        return string_bytes[0..std.mem.findScalar(u8, string_bytes, 0).? :0];
     }
 };
 
diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig
index 1e01ff508af3a29367f9cfbb1ea74d412147d70a..3ebad4dee2a9235f641e12be27684d247bfd2de1 100644
--- a/src/codegen/x86_64/abi.zig
+++ b/src/codegen/x86_64/abi.zig
@@ -318,7 +318,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
             // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument
             // is passed in memory."
             if (ty_size > 16 and (result[0] != .sse or
-                std.mem.indexOfNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
+                std.mem.findNone(Class, result[1..], &.{ .sseup, .none }) != null)) return Class.stack;
 
             // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE."
             for (&result, 0..) |*class, i| switch (class.*) {
diff --git a/src/codegen/x86_64/encoder.zig b/src/codegen/x86_64/encoder.zig
index d18497cf08b640064083c4322feaab825f0bb849..a3c8a34714bdc033c5105ddf65e20f5b30e198eb 100644
--- a/src/codegen/x86_64/encoder.zig
+++ b/src/codegen/x86_64/encoder.zig
@@ -1171,7 +1171,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []co
     defer testing.allocator.free(expected_fmt);
     const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
     defer testing.allocator.free(given_fmt);
-    const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
+    const idx = std.mem.findDiff(u8, expected_fmt, given_fmt).?;
     const padding = try testing.allocator.alloc(u8, idx + 5);
     defer testing.allocator.free(padding);
     @memset(padding, ' ');
diff --git a/src/libs/mingw/Preprocessor.zig b/src/libs/mingw/Preprocessor.zig
index 9098b6013a4179ba15de85707d70d290f09bd116..f6606eb54cd0f2ea46a85194dd79674115256499 100644
--- a/src/libs/mingw/Preprocessor.zig
+++ b/src/libs/mingw/Preprocessor.zig
@@ -15,7 +15,7 @@ const RawTokenList = std.ArrayList(Token);
 const ExpandBuf = std.ArrayList(Token);
 
 const Preprocessor = @This();
-const DefineMap = std.StringArrayHashMapUnmanaged(Macro);
+const DefineMap = std.array_hash_map.String(Macro);
 
 const GeneratedTokens = std.ArrayList(u8);
 
@@ -29,7 +29,7 @@ pub const Source = struct {
     buf: []const u8,
 };
 
-sources: std.StringArrayHashMapUnmanaged(Source) = .empty,
+sources: std.array_hash_map.String(Source) = .empty,
 
 arena: Allocator,
 io: std.Io,
diff --git a/src/libs/mingw/def.zig b/src/libs/mingw/def.zig
index f1c112d16e0e49249faeaaf159f7e2b79e277861..0d67f4fe33539c9a7a25b648a6306f1251187333 100644
--- a/src/libs/mingw/def.zig
+++ b/src/libs/mingw/def.zig
@@ -61,7 +61,7 @@ pub const ModuleDefinition = struct {
                 // or ? for C++ functions). Vectorcall functions won't have any
                 // fixed prefix, but the function base name will still be at least
                 // one char.
-                const name_len_without_at_suffix = std.mem.indexOfScalarPos(u8, e.name, 1, '@') orelse e.name.len;
+                const name_len_without_at_suffix = std.mem.findScalarPos(u8, e.name, 1, '@') orelse e.name.len;
                 e.name = e.name[0..name_len_without_at_suffix];
             }
         }
@@ -452,7 +452,7 @@ pub const Parser = struct {
                         var ext_name_needs_underscore = false;
                         if (self.machine_type == .I386) {
                             const is_decorated = isDecorated(name_tok.slice(self.tokenizer.source), self.module_definition_type);
-                            const is_forward_target = ext_name_tok != null and std.mem.indexOfScalar(u8, name_tok.slice(self.tokenizer.source), '.') != null;
+                            const is_forward_target = ext_name_tok != null and std.mem.findScalar(u8, name_tok.slice(self.tokenizer.source), '.') != null;
                             name_needs_underscore = !is_decorated and !is_forward_target;
 
                             if (ext_name_tok) |ext_name| {
@@ -578,9 +578,9 @@ pub const Parser = struct {
         // themselves can start with an underscore, while a second one still needs
         // to be added.
         if (std.mem.startsWith(u8, symbol, "@")) return true;
-        if (std.mem.indexOf(u8, symbol, "@@") != null) return true;
+        if (std.mem.find(u8, symbol, "@@") != null) return true;
         if (std.mem.startsWith(u8, symbol, "?")) return true;
-        if (module_definition_type != .mingw and std.mem.indexOfScalar(u8, symbol, '@') != null) return true;
+        if (module_definition_type != .mingw and std.mem.findScalar(u8, symbol, '@') != null) return true;
         return false;
     }
 
diff --git a/src/libs/mingw/implib.zig b/src/libs/mingw/implib.zig
index f8ee4858e66d84de84c337c92f04e7c5363442e1..0a4deb7aeb87ac62939fc7a8fd1f6e3d6a1a7966 100644
--- a/src/libs/mingw/implib.zig
+++ b/src/libs/mingw/implib.zig
@@ -351,7 +351,7 @@ fn getNameType(
     // the leading underscore. In MinGW on the other hand, a decorated
     // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
     if (std.mem.startsWith(u8, ext_name, "_") and
-        std.mem.indexOfScalar(u8, ext_name, '@') != null and
+        std.mem.findScalar(u8, ext_name, '@') != null and
         module_definition_type != .mingw)
         return .NAME;
     if (!std.mem.eql(u8, symbol, ext_name))
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index ad85216499ff793a0737fa4082814bfbd1a001e4..729e6393845bdcd5d8edbf98ea8fa126f718e978 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -621,7 +621,7 @@ pub const LongNamesTable = struct {
         }
 
         pub fn hash(_: Adapter, key: []const u8) u32 {
-            assert(std.mem.indexOfScalar(u8, key, 0) == null);
+            assert(std.mem.findScalar(u8, key, 0) == null);
             return std.array_hash_map.hashString(key);
         }
     };
@@ -711,7 +711,7 @@ pub const ExportTable = struct {
         }
 
         pub fn hash(_: Adapter, key: []const u8) u32 {
-            assert(std.mem.indexOfScalar(u8, key, 0) == null);
+            assert(std.mem.findScalar(u8, key, 0) == null);
             return std.array_hash_map.hashString(key);
         }
     };
@@ -759,7 +759,7 @@ pub const ImportTable = struct {
         }
 
         pub fn hash(_: Adapter, key: []const u8) u32 {
-            assert(std.mem.indexOfScalar(u8, key, 0) == null);
+            assert(std.mem.findScalar(u8, key, 0) == null);
             return std.array_hash_map.hashString(key);
         }
     };
@@ -822,7 +822,7 @@ pub const String = enum(u32) {
 
     pub fn toSlice(s: String, coff: *Coff) [:0]const u8 {
         const slice = coff.string_bytes.items[@backingInt(s)..];
-        return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0];
+        return slice[0..std.mem.findScalar(u8, slice, 0).? :0];
     }
 
     pub fn toOptional(s: String) String.Optional {
@@ -3535,7 +3535,7 @@ fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 {
     // Otherwise, we want to keep the full name so that this sort can occur correctly when
     // the object is finally linked into an image.
     return if (coff.isImage())
-        name[0 .. std.mem.indexOfScalar(u8, name, '$') orelse name.len]
+        name[0 .. std.mem.findScalar(u8, name, '$') orelse name.len]
     else
         name;
 }
@@ -5737,7 +5737,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
     const gpa = comp.gpa;
     const max_notes = 4;
 
-    var undef_indices: std.ArrayListUnmanaged(u32) = .empty;
+    var undef_indices: std.ArrayList(u32) = .empty;
     for (coff.relocs.items, 0..) |reloc, reloc_i| {
         if (reloc.flags.free) continue;
         const target_sym = reloc.target.get(coff);
@@ -6987,7 +6987,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
                             continue;
 
                         import_hint_name_index = @intCast(import_hint_name_align.forward(
-                            std.mem.indexOfScalarPos(
+                            std.mem.findScalarPos(
                                 u8,
                                 import_hint_name_slice,
                                 import_hint_name_index,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index e22680a44a450739239051ad62d27067d2efe327..04d4f9235e12f22c3ee7f012c48d43f323ea38a1 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -2173,7 +2173,7 @@ fn sortInitFini(self: *Elf) !void {
             => is_init_fini = true,
             else => {
                 const name = self.getShString(shdr.sh_name);
-                is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null;
+                is_ctor_dtor = mem.find(u8, name, ".ctors") != null or mem.find(u8, name, ".dtors") != null;
             },
         }
         if (!is_init_fini and !is_ctor_dtor) continue;
@@ -3702,7 +3702,7 @@ fn shString(
     off: u32,
 ) [:0]const u8 {
     const slice = shstrtab[off..];
-    return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
+    return slice[0..mem.findScalar(u8, slice, 0).? :0];
 }
 
 pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
@@ -4376,7 +4376,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
 
 pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 {
     const slice = strtab[off..];
-    return slice[0..mem.indexOfScalar(u8, slice, 0).? :0];
+    return slice[0..mem.findScalar(u8, slice, 0).? :0];
 }
 
 pub fn pwriteAll(elf_file: *Elf, bytes: []const u8, offset: u64) error{AlreadyReported}!void {
diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig
index ae997c5b9bc16e806ca86d0889ff95df094dafdf..7be90fc558f72eaabeec930aa83f6e7f5e71b975 100644
--- a/src/link/Elf/Archive.zig
+++ b/src/link/Elf/Archive.zig
@@ -118,7 +118,7 @@ pub fn parse(
 
 pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 {
     const slice = strtab[off..];
-    return slice[0..mem.indexOfScalar(u8, slice, '\n').? :'\n'];
+    return slice[0..mem.findScalar(u8, slice, '\n').? :'\n'];
 }
 
 pub fn setArHdr(opts: struct {
diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig
index be921d285bf96e557a24a04ed53a3f84052bfa2a..b0085f18a404a767553ffbf99ccc63bea7672e2a 100644
--- a/src/link/Elf2.zig
+++ b/src/link/Elf2.zig
@@ -3010,7 +3010,7 @@ const StringTable = struct {
         }
 
         pub fn hash(_: Adapter, key: []const u8) u64 {
-            assert(std.mem.indexOfScalar(u8, key, 0) == null);
+            assert(std.mem.findScalar(u8, key, 0) == null);
             return std.hash_map.hashString(key);
         }
     };
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 77441748d57ef2ad1823f01d2bad18c3b9c1a5e5..3dddf5f78ebc396599c14c666f4b15c082fbce0f 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -1070,7 +1070,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool {
         if (mem.startsWith(u8, dirname, "/usr/lib")) return true;
         if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| {
             const basename = fs.path.basename(install_name);
-            if (mem.indexOfScalar(u8, path, '.')) |index| {
+            if (mem.findScalar(u8, path, '.')) |index| {
                 if (mem.eql(u8, basename, path[0..index])) return true;
             }
         }
@@ -1739,14 +1739,14 @@ fn initSyntheticSections(self: *MachO) !void {
                     });
                 }
             } else if (eatPrefix(name, "section$start$")) |actual_name| {
-                const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
+                const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
                 const segname = actual_name[0..sep]; // TODO check segname is valid
                 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
                 if (self.getSectionByName(segname, sectname) == null) {
                     _ = try self.addSection(segname, sectname, .{});
                 }
             } else if (eatPrefix(name, "section$end$")) |actual_name| {
-                const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
+                const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
                 const segname = actual_name[0..sep]; // TODO check segname is valid
                 const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid
                 if (self.getSectionByName(segname, sectname) == null) {
@@ -1767,7 +1767,7 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {
 fn getSegmentRank(segname: []const u8) u8 {
     if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;
     if (mem.eql(u8, segname, "__LINKEDIT")) return 0xf;
-    if (mem.indexOf(u8, segname, "ZIG")) |_| return 0xe;
+    if (mem.find(u8, segname, "ZIG")) |_| return 0xe;
     if (mem.startsWith(u8, segname, "__TEXT")) return 0x1;
     if (mem.startsWith(u8, segname, "__DATA_CONST")) return 0x2;
     if (mem.startsWith(u8, segname, "__DATA")) return 0x3;
@@ -2342,7 +2342,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
                 }
             } else if (mem.startsWith(u8, name, "section$start$")) {
                 const actual_name = name["section$start$".len..];
-                const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
+                const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
                 const segname = actual_name[0..sep];
                 const sectname = actual_name[sep + 1 ..];
                 if (self.getSectionByName(segname, sectname)) |sect_id| {
@@ -2352,7 +2352,7 @@ fn allocateSyntheticSymbols(self: *MachO) void {
                 }
             } else if (mem.startsWith(u8, name, "section$end$")) {
                 const actual_name = name["section$end$".len..];
-                const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic
+                const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic
                 const segname = actual_name[0..sep];
                 const sectname = actual_name[sep + 1 ..];
                 if (self.getSectionByName(segname, sectname)) |sect_id| {
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index a733e1a5b6c9b3911e27e5e60e1ae4e6faed54a5..91860f45986b106bed46fbf37e9ac35133ff5b49 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -45,7 +45,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
                 const amt = try handle.readPositionalAll(io, buf, pos);
                 if (amt != len) return error.InputOutput;
                 pos += len;
-                const actual_len = mem.indexOfScalar(u8, buf, @as(u8, 0)) orelse len;
+                const actual_len = mem.findScalar(u8, buf, @as(u8, 0)) orelse len;
                 break :name buf[0..actual_len];
             }
             unreachable;
@@ -161,7 +161,7 @@ pub const ar_hdr = extern struct {
     fn name(self: *const ar_hdr) ?[]const u8 {
         const value = &self.ar_name;
         if (mem.startsWith(u8, value, "#1/")) return null;
-        const sentinel = mem.indexOfScalar(u8, value, '/') orelse value.len;
+        const sentinel = mem.findScalar(u8, value, '/') orelse value.len;
         return value[0..sentinel];
     }
 
diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig
index 7ac8e28881417cde1fcb9da5a9cc90eaf43b8036..60172cf6382342fc6f40080b31724d8369a504ea 100644
--- a/src/link/MachO/Symbol.zig
+++ b/src/link/MachO/Symbol.zig
@@ -43,7 +43,7 @@ pub fn isSymbolStab(symbol: Symbol, macho_file: *MachO) bool {
 
 pub fn isTlvInit(symbol: Symbol, macho_file: *MachO) bool {
     const name = symbol.getName(macho_file);
-    return std.mem.indexOf(u8, name, "$tlv$init") != null;
+    return std.mem.find(u8, name, "$tlv$init") != null;
 }
 
 pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool {
diff --git a/src/link/MachO/dyld_info/Trie.zig b/src/link/MachO/dyld_info/Trie.zig
index b1fdc18d7593608ea6b3eb732adb46548096352d..92c22967f3e23647d84b399ffdc6ac92a60f2f8e 100644
--- a/src/link/MachO/dyld_info/Trie.zig
+++ b/src/link/MachO/dyld_info/Trie.zig
@@ -54,7 +54,7 @@ fn putNode(self: *Trie, node_index: Node.Index, allocator: Allocator, label: []c
     // Check for match with edges from this node.
     for (self.nodes.items(.edges)[node_index].items) |edge_index| {
         const edge = &self.edges.items[edge_index];
-        const match = mem.indexOfDiff(u8, edge.label, label) orelse return edge.node;
+        const match = mem.findDiff(u8, edge.label, label) orelse return edge.node;
         if (match == 0) continue;
         if (match == edge.label.len) return self.putNode(edge.node, allocator, label[match..]);
 
@@ -351,7 +351,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
     defer testing.allocator.free(expected_fmt);
     const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
     defer testing.allocator.free(given_fmt);
-    const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
+    const idx = mem.findDiff(u8, expected_fmt, given_fmt).?;
     const padding = try testing.allocator.alloc(u8, idx + 5);
     defer testing.allocator.free(padding);
     @memset(padding, ' ');
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig
index 10d01c2055ff5bf5c1d3734b4a4ae43411d8cc14..aecbc039266604cc905586b71032e91d83b096d0 100644
--- a/src/link/SpirV.zig
+++ b/src/link/SpirV.zig
@@ -25,10 +25,10 @@ const Mir = @import("../codegen/spirv/Mir.zig");
 const Linker = @This();
 
 base: link.File,
-fragments: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Mir) = .empty,
-pending_navs: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
-entry_points: std.ArrayListUnmanaged(EntryPointDecl) = .empty,
-external_objects: std.ArrayListUnmanaged(ExternalObject) = .empty,
+fragments: std.array_hash_map.Auto(InternPool.Nav.Index, Mir) = .empty,
+pending_navs: std.ArrayList(InternPool.Nav.Index) = .empty,
+entry_points: std.ArrayList(EntryPointDecl) = .empty,
+external_objects: std.ArrayList(ExternalObject) = .empty,
 
 const EntryPointDecl = struct {
     nav: InternPool.Nav.Index,
@@ -363,16 +363,16 @@ fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOf
     }
 
     // Resolve Zig extern navs against external objects.
-    var ext_id_offsets: std.ArrayListUnmanaged(Word) = .empty;
+    var ext_id_offsets: std.ArrayList(Word) = .empty;
     defer ext_id_offsets.deinit(gpa);
     try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len);
 
     var unresolved_extern_count: u32 = 0;
-    var resolved_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+    var resolved_ids: std.array_hash_map.Auto(Id, void) = .empty;
     defer resolved_ids.deinit(gpa);
 
     if (maybe_ip) |ip| {
-        var extern_name_map: std.StringArrayHashMapUnmanaged(InternPool.Nav.Index) = .empty;
+        var extern_name_map: std.array_hash_map.String(InternPool.Nav.Index) = .empty;
         defer extern_name_map.deinit(gpa);
 
         var nav_it = nav_final_ids.iterator();
@@ -518,14 +518,14 @@ fn mergeZigFragments(
     frag_infos: []const FragmentInfo,
     nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id),
     uav_final_ids: *const std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass }, Id),
-    resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+    resolved_ids: *const std.array_hash_map.Auto(Id, void),
     maybe_ip: ?*InternPool,
 ) error{OutOfMemory}!void {
     for (linker.fragments.values(), frag_infos) |*mir, frag_info| {
         var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty;
         defer id_remap.deinit(gpa);
 
-        var resolved_local_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+        var resolved_local_ids: std.array_hash_map.Auto(Id, void) = .empty;
         defer resolved_local_ids.deinit(gpa);
 
         for (mir.nav_refs) |ref| {
@@ -569,7 +569,7 @@ fn remapFilteredInsts(
     id_offset: Word,
     id_remap: *const std.AutoHashMapUnmanaged(Id, Id),
     parser: *BinaryModule.Parser,
-    skip_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+    skip_ids: *const std.array_hash_map.Auto(Id, void),
     mode: FilterMode,
 ) error{OutOfMemory}!void {
     if (words.len == 0) return;
@@ -887,9 +887,9 @@ fn appendExternalObjects(
     has_linkage: *bool,
     keep_entry_points: bool,
     is_obj: bool,
-    resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void),
+    resolved_ids: *const std.array_hash_map.Auto(Id, void),
 ) error{OutOfMemory}!void {
-    var export_map: std.StringArrayHashMapUnmanaged(Id) = .empty;
+    var export_map: std.array_hash_map.String(Id) = .empty;
     defer export_map.deinit(gpa);
 
     for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| {
@@ -908,7 +908,7 @@ fn appendExternalObjects(
     }
     for (per_obj_remaps) |*m| m.* = .empty;
 
-    var resolved_linkage_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty;
+    var resolved_linkage_ids: std.array_hash_map.Auto(Id, void) = .empty;
     defer resolved_linkage_ids.deinit(gpa);
 
     for (resolved_ids.keys()) |id| {
diff --git a/src/link/SpirV/dedup_types.zig b/src/link/SpirV/dedup_types.zig
index df0d9a29dd78258acda42be564a14ab748638bce..8841c4185033c8ace7131236f0e549ef10745118 100644
--- a/src/link/SpirV/dedup_types.zig
+++ b/src/link/SpirV/dedup_types.zig
@@ -85,7 +85,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
 
         for (inst.operands, 0..) |word, i| {
             if (i == result_id_index) continue;
-            if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) != null) {
+            if (std.mem.findScalar(u16, id_offsets.items, @intCast(i)) != null) {
                 const canonical = id_remap.get(@fromBackingInt(@intCast(word))) orelse @as(Id, @fromBackingInt(@intCast(word)));
                 try key_words.append(gpa, @backingInt(canonical));
             } else {
@@ -182,7 +182,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
         } else null;
 
         for (inst_slice, 0..) |*word, i| {
-            if (std.mem.indexOfScalar(u16, id_offsets.items, @intCast(i)) == null) continue;
+            if (std.mem.findScalar(u16, id_offsets.items, @intCast(i)) == null) continue;
             max_id = @max(max_id, word.*);
             if (maybe_result_id_index != null and i == maybe_result_id_index.?) continue;
 
diff --git a/src/link/SpirV/prune_unused.zig b/src/link/SpirV/prune_unused.zig
index 2ca052152fdbb371e05a8d8fc5aac95fa8402f11..a41b0d878d07b7c3e3179429dae74e27aaf044b8 100644
--- a/src/link/SpirV/prune_unused.zig
+++ b/src/link/SpirV/prune_unused.zig
@@ -187,7 +187,7 @@ fn markAlive(
     parser: *BinaryModule.Parser,
     binary: BinaryModule,
     inst: BinaryModule.Instruction,
-    alive: *std.DynamicBitSetUnmanaged,
+    alive: *std.bit_set.Dynamic,
     id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32),
     code_offsets: *const std.ArrayList(usize),
     id_offset_buf: *std.ArrayList(u16),
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 495b9d06603191ca2b503e98f413b9ab3ead52d9..9fba1510ba1f847d2c1ed1cdd2f15eab3c30504f 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -2539,14 +2539,14 @@ pub const String = enum(u32) {
         }
 
         pub fn hash(_: @This(), adapted_key: []const u8) u64 {
-            assert(mem.indexOfScalar(u8, adapted_key, 0) == null);
+            assert(mem.findScalar(u8, adapted_key, 0) == null);
             return std.hash_map.hashString(adapted_key);
         }
     };
 
     pub fn slice(index: String, wasm: *const Wasm) [:0]const u8 {
         const start_slice = wasm.string_bytes.items[@backingInt(index)..];
-        return start_slice[0..mem.indexOfScalar(u8, start_slice, 0).? :0];
+        return start_slice[0..mem.findScalar(u8, start_slice, 0).? :0];
     }
 
     pub fn toOptional(i: String) OptionalString {
@@ -4332,7 +4332,7 @@ pub fn internOptionalString(wasm: *Wasm, optional_bytes: ?[]const u8) Allocator.
 }
 
 pub fn internString(wasm: *Wasm, bytes: []const u8) Allocator.Error!String {
-    assert(mem.indexOfScalar(u8, bytes, 0) == null);
+    assert(mem.findScalar(u8, bytes, 0) == null);
     wasm.string_bytes_lock.lock();
     defer wasm.string_bytes_lock.unlock();
     const gpa = wasm.base.comp.gpa;
@@ -4363,7 +4363,7 @@ pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype)
 }
 
 pub fn getExistingString(wasm: *const Wasm, bytes: []const u8) ?String {
-    assert(mem.indexOfScalar(u8, bytes, 0) == null);
+    assert(mem.findScalar(u8, bytes, 0) == null);
     return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{
         .bytes = wasm.string_bytes.items,
     }));
diff --git a/src/link/Wasm/Archive.zig b/src/link/Wasm/Archive.zig
index 65a1ee313b8c6bc5e8710728cd877284c47b544f..48665264f3cab69532a8e70d371fe506578d3ea8 100644
--- a/src/link/Wasm/Archive.zig
+++ b/src/link/Wasm/Archive.zig
@@ -45,7 +45,7 @@ const Header = extern struct {
 
     fn nameOrIndex(archive: Header) !NameOrIndex {
         const value = getValue(&archive.name);
-        const slash_index = mem.indexOfScalar(u8, value, '/') orelse return error.MalformedArchive;
+        const slash_index = mem.findScalar(u8, value, '/') orelse return error.MalformedArchive;
         const len = value.len;
         if (slash_index == len - 1) {
             // Name stored directly
diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig
index 9c15adf65029f90fd95b13f57599bc9bcb6f9bcf..e80d768ae122c3a92ec66ed98e202dc5b6c242ed 100644
--- a/src/link/Wasm/Flush.zig
+++ b/src/link/Wasm/Flush.zig
@@ -1925,7 +1925,7 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void {
 
 fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } {
     const start = @intFromBool(name.len >= 1 and name[0] == '.');
-    const pivot = mem.indexOfScalarPos(u8, name, start, '.') orelse name.len;
+    const pivot = mem.findScalarPos(u8, name, start, '.') orelse name.len;
     return .{ name[0..pivot], name[pivot..] };
 }
 
@@ -2092,7 +2092,7 @@ fn emitTagNameTable(
     const ptr_size_bytes: usize = if (is64) 8 else 4;
     try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len);
     for (tag_name_offs) |off| {
-        const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);
+        const name_len: u32 = @intCast(mem.findScalar(u8, tag_name_bytes[off..], 0).?);
         if (is64) {
             mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), base + off, .little);
             mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), name_len, .little);
@@ -2119,7 +2119,7 @@ fn emitRelocatableNameTable(
     try code.ensureUnusedCapacity(gpa, @as(usize, ptr_size) * 2 * name_offs.len);
     try relocs.ensureUnusedCapacity(gpa, name_offs.len);
     for (name_offs) |off| {
-        const name_len: u32 = @intCast(mem.indexOfScalar(u8, name_bytes[off..], 0).?);
+        const name_len: u32 = @intCast(mem.findScalar(u8, name_bytes[off..], 0).?);
         const reloc_offset = output_offset + @as(u32, @intCast(code.items.len - table_start));
         switch (ptr_size) {
             4 => {
diff --git a/src/main.zig b/src/main.zig
index 4faeaebcecd927c8bdd3468ebc32453a74fc9c18..ff915761b592ad2a1f9a6fc66336b26e9b43bc16 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2148,7 +2148,7 @@ fn buildOutputType(
                                 preprocessor_arg[0] == '-' and
                                 preprocessor_arg[2] != '-')
                             {
-                                if (mem.indexOfScalar(u8, preprocessor_arg, '=')) |equals_pos| {
+                                if (mem.findScalar(u8, preprocessor_arg, '=')) |equals_pos| {
                                     const key = preprocessor_arg[0..equals_pos];
                                     const value = preprocessor_arg[equals_pos + 1 ..];
                                     try preprocessor_args.append(key);
@@ -2170,7 +2170,7 @@ fn buildOutputType(
                                 linker_arg[0] == '-' and
                                 linker_arg[2] != '-')
                             {
-                                if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
+                                if (mem.findScalar(u8, linker_arg, '=')) |equals_pos| {
                                     const key = linker_arg[0..equals_pos];
                                     const value = linker_arg[equals_pos + 1 ..];
 
@@ -2378,7 +2378,7 @@ fn buildOutputType(
                         // Handle joined args like `--dependency-file=foo.d`.
                         // Must be prefixed with 1 or 2 dashes.
                         if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') {
-                            if (mem.indexOfScalar(u8, it.only_arg, '=')) |equals_pos| {
+                            if (mem.findScalar(u8, it.only_arg, '=')) |equals_pos| {
                                 const key = it.only_arg[0..equals_pos];
                                 const value = it.only_arg[equals_pos + 1 ..];
 
diff --git a/src/target.zig b/src/target.zig
index c64fd988cf4de9c881a8e79041ea8f7b80b099d0..d67766c3691ba6fda8cb86961e889458629d7360 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -680,14 +680,14 @@ pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu
     const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index));
 
     if (feature_tag == .sramecc) {
-        if (std.mem.indexOfScalar(
+        if (std.mem.findScalar(
             *const std.Target.Cpu.Model,
             sramecc_only ++ xnack_or_sramecc,
             target.cpu.model,
         )) |_| return true;
     }
     if (feature_tag == .xnack) {
-        if (std.mem.indexOfScalar(
+        if (std.mem.findScalar(
             *const std.Target.Cpu.Model,
             xnack_or_sramecc,
             target.cpu.model,
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index af5dcfdddd6fd1c7671f88ff812637bfbcdfd794..c629f42381afb196a4621d6530ba106e788b52b3 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -491,7 +491,7 @@ pub fn lowerToBuildSteps(
 
     for (self.cases.items) |case| {
         for (options.test_filters) |test_filter| {
-            if (std.mem.indexOf(u8, case.name, test_filter)) |_| break;
+            if (std.mem.find(u8, case.name, test_filter)) |_| break;
         } else if (options.test_filters.len > 0) continue;
 
         if (case.case.? == .Error and options.skip_compile_errors) continue;
@@ -524,7 +524,7 @@ pub fn lowerToBuildSteps(
 
         if (options.test_target_filters.len > 0) {
             for (options.test_target_filters) |filter| {
-                if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+                if (std.mem.find(u8, triple_txt, filter) != null) break;
             } else continue;
         }
 
diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig
index b951e3c86595302d1ee16101f4f810bcaf21ab24..0e20799f3949884c437bbd39931c29f93a41d5b5 100644
--- a/test/src/Debugger.zig
+++ b/test/src/Debugger.zig
@@ -2384,13 +2384,13 @@ fn addTest(
 ) void {
     if (db.options.test_filters.len > 0) {
         for (db.options.test_filters) |test_filter| {
-            if (std.mem.indexOf(u8, name, test_filter) != null) break;
+            if (std.mem.find(u8, name, test_filter) != null) break;
         } else return;
     }
     if (db.options.test_target_filters.len > 0) {
         const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM");
         for (db.options.test_target_filters) |filter| {
-            if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+            if (std.mem.find(u8, triple_txt, filter) != null) break;
         } else return;
     }
     const files_wf = db.b.addWriteFiles();
diff --git a/test/src/ErrorTrace.zig b/test/src/ErrorTrace.zig
index c4150eded5d4b17fffc2a386d3c7b9411ded6665..b0ce8b05bb39687429ffb8eec893f254d4c4813a 100644
--- a/test/src/ErrorTrace.zig
+++ b/test/src/ErrorTrace.zig
@@ -82,7 +82,7 @@ fn addCaseConfig(
     });
     if (self.test_filters.len > 0) {
         for (self.test_filters) |test_filter| {
-            if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+            if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
         } else return;
     }
 
diff --git a/test/src/Libc.zig b/test/src/Libc.zig
index d2113893325821c63a441eba99ea06f1a4610402..12a4468b1f6d33b7494d7fb87b43636533e8ed90 100644
--- a/test/src/Libc.zig
+++ b/test/src/Libc.zig
@@ -49,7 +49,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
     if (libc.options.test_target_filters.len > 0) {
         const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM");
         for (libc.options.test_target_filters) |filter| {
-            if (std.mem.indexOf(u8, triple_txt, filter)) |_| break;
+            if (std.mem.find(u8, triple_txt, filter)) |_| break;
         } else return;
     }
 
@@ -82,7 +82,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void {
 
             const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize });
             for (libc.options.test_filters) |test_filter| {
-                if (std.mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+                if (std.mem.find(u8, annotated_case_name, test_filter)) |_| break;
             } else if (libc.options.test_filters.len > 0) continue;
 
             const mod = libc.b.createModule(.{
diff --git a/test/src/Link.zig b/test/src/Link.zig
index 0c64ae5648333aabf1bfc56090d929341772294c..f0266923e34a380c1e5547c3f180b2d6febbe71c 100644
--- a/test/src/Link.zig
+++ b/test/src/Link.zig
@@ -8,7 +8,7 @@ use_lld: bool,
 link_libc: bool,
 test_filters: []const []const u8,
 update_step: ?*Step.UpdateSourceFiles,
-updated_snapshots: std.StringArrayHashMapUnmanaged(void),
+updated_snapshots: std.array_hash_map.String(void),
 max_rss: usize,
 
 pub fn includeTest(self: *Link, prefix: []const u8) ?Case {
diff --git a/test/src/LlvmIr.zig b/test/src/LlvmIr.zig
index 310d6426188bba216465b9c0ea126946c47cf9ca..fc0fddeb32f4893af6b38d1ef80c780fdae4676f 100644
--- a/test/src/LlvmIr.zig
+++ b/test/src/LlvmIr.zig
@@ -77,14 +77,14 @@ pub fn addCase(self: *LlvmIr, case: TestCase) void {
     if (self.options.test_target_filters.len > 0) {
         const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM");
         for (self.options.test_target_filters) |filter| {
-            if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+            if (std.mem.find(u8, triple_txt, filter) != null) break;
         } else return;
     }
 
     const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM");
     if (self.options.test_filters.len > 0) {
         for (self.options.test_filters) |filter| {
-            if (std.mem.indexOf(u8, name, filter) != null) break;
+            if (std.mem.find(u8, name, filter) != null) break;
         } else return;
     }
 
diff --git a/test/src/RunTranslatedC.zig b/test/src/RunTranslatedC.zig
index 74e059cc599f9cb3edac29c1562b5b6d3adc2551..7d147aeceacf88c2658230ef0d48a7e7ae166bb2 100644
--- a/test/src/RunTranslatedC.zig
+++ b/test/src/RunTranslatedC.zig
@@ -68,7 +68,7 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
 
     const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable;
     for (self.test_filters) |test_filter| {
-        if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+        if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
     } else if (self.test_filters.len > 0) return;
 
     const write_src = b.addWriteFiles();
diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig
index a10b70fe280d5594a853e2ca37238891d9af41ff..23938cbf1ade2733f8220bbb03612c183ad7e27a 100644
--- a/test/src/StackTrace.zig
+++ b/test/src/StackTrace.zig
@@ -200,7 +200,7 @@ fn addCaseInstance(
     });
     if (self.test_filters.len > 0) {
         for (self.test_filters) |test_filter| {
-            if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+            if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
         } else return;
     }
 
diff --git a/test/src/TranslateC.zig b/test/src/TranslateC.zig
index 57aaea6e0cacf946fc9d351eb9a7db04e4bd407d..c8cc4e3fd009f3dd3f983d042549b45b7da6e571 100644
--- a/test/src/TranslateC.zig
+++ b/test/src/TranslateC.zig
@@ -90,7 +90,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
     const translate_c_cmd = "translate-c";
     const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable;
     for (self.test_filters) |test_filter| {
-        if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
+        if (mem.find(u8, annotated_case_name, test_filter)) |_| break;
     } else if (self.test_filters.len > 0) return;
 
     const target = b.resolveTargetQuery(case.target);
@@ -99,7 +99,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
         const triple_txt = target.query.zigTriple(b.allocator) catch @panic("OOM");
 
         for (self.test_target_filters) |filter| {
-            if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+            if (std.mem.find(u8, triple_txt, filter) != null) break;
         } else return;
     }
 
diff --git a/test/src/convert-stack-trace.zig b/test/src/convert-stack-trace.zig
index 5d7356a2d48e92e8577d4c3013a062dec0d63899..e42fd6860c76ce0f8986d06501f310862e39a3ca 100644
--- a/test/src/convert-stack-trace.zig
+++ b/test/src/convert-stack-trace.zig
@@ -52,13 +52,13 @@ pub fn main(init: std.process.Init) !void {
             continue;
         }
 
-        const src_pos_end = std.mem.indexOf(u8, in_line, ": 0x") orelse {
+        const src_pos_end = std.mem.find(u8, in_line, ": 0x") orelse {
             try w.writeAll(in_line);
             continue;
         };
         const src_pos_start = b: {
             const postfix = ".zig:";
-            const postfix_index = std.mem.lastIndexOf(u8, in_line[0..src_pos_end], postfix) orelse {
+            const postfix_index = std.mem.findLast(u8, in_line[0..src_pos_end], postfix) orelse {
                 try w.writeAll(in_line);
                 continue;
             };
@@ -89,7 +89,7 @@ pub fn main(init: std.process.Init) !void {
         // ...with that first '_' being replaced by its basename.
 
         const src_path = in_line[0..src_pos_start];
-        const basename_start = if (std.mem.lastIndexOfAny(u8, src_path, "/\\")) |i| i + 1 else 0;
+        const basename_start = if (std.mem.findLastAny(u8, src_path, "/\\")) |i| i + 1 else 0;
         const symbol_start = addr_end + " in ".len;
         try w.writeAll(in_line[basename_start..src_pos_end]);
         try w.writeAll(": [address] in ");
diff --git a/test/tests.zig b/test/tests.zig
index 90442edf52c9135eaf901c075828191cae6e45f3..b543d0d48f80e74bb943fae1da93a868278e8363 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -2542,13 +2542,13 @@ pub fn addStandaloneTests(
             .enable_ios_sdk = enable_ios_sdk,
             .enable_macos_sdk = enable_macos_sdk,
             .enable_symlinks_windows = enable_symlinks_windows,
-            .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .debug) == null,
-            .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .safe) == null,
-            .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .fast) == null,
-            .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .small) == null,
+            .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
+            .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
+            .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
+            .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
         });
         const test_cases_dep_step = test_cases_dep.builder.default_step;
-        test_cases_dep_step.name = b.dupe(test_cases_dep_name);
+        test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
         step.dependOn(test_cases_dep.builder.default_step);
     }
     return step;
@@ -2862,7 +2862,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
 
         if (options.test_target_filters.len > 0) {
             for (options.test_target_filters) |filter| {
-                if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+                if (std.mem.find(u8, triple_txt, filter) != null) break;
             } else continue;
         }
 
@@ -3160,7 +3160,7 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
 
         if (options.test_target_filters.len > 0) {
             for (options.test_target_filters) |filter| {
-                if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+                if (std.mem.find(u8, triple_txt, filter) != null) break;
             } else continue;
         }
 
@@ -3249,7 +3249,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step {
 
         if (options.test_target_filters.len > 0) {
             for (options.test_target_filters) |filter| {
-                if (std.mem.indexOf(u8, triple_txt, filter) != null) break;
+                if (std.mem.find(u8, triple_txt, filter) != null) break;
             } else continue;
         }
 
@@ -3374,7 +3374,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
         if (std.mem.endsWith(u8, entry.basename, ".swp")) continue;
 
         for (test_filters) |test_filter| {
-            if (std.mem.indexOf(u8, entry.path, test_filter)) |_| break;
+            if (std.mem.find(u8, entry.path, test_filter)) |_| break;
         } else if (test_filters.len > 0) continue;
 
         switch (entry.kind) {
diff --git a/tools/docgen.zig b/tools/docgen.zig
index 9f182f350cc73069a44bfe7b2cc52ade250f228e..5e78dbecc98f37d1d4186011a2601683a29713e1 100644
--- a/tools/docgen.zig
+++ b/tools/docgen.zig
@@ -712,10 +712,10 @@ fn tokenizeAndPrintRaw(
         next_tok_is_fn = false;
 
         const token = tokenizer.next();
-        if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {
+        if (mem.find(u8, src[index..token.loc.start], "//")) |comment_start_off| {
             // render one comment
             const comment_start = index + comment_start_off;
-            const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
+            const comment_end_off = mem.find(u8, src[comment_start..token.loc.start], "\n");
             const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
 
             try writeEscapedLines(out, src[index..comment_start]);
diff --git a/tools/doctest.zig b/tools/doctest.zig
index fcd67e8458a31ea03323b87cbfb222fc31852f94..b653b84a8e3195d01c061921428273d3c351839a 100644
--- a/tools/doctest.zig
+++ b/tools/doctest.zig
@@ -383,7 +383,7 @@ fn printOutput(
                     fatal("example compile crashed", .{});
                 },
             }
-            if (mem.indexOf(u8, result.stderr, error_match) == null) {
+            if (mem.find(u8, result.stderr, error_match) == null) {
                 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
                 fatal("example did not have expected compile error", .{});
             }
@@ -438,7 +438,7 @@ fn printOutput(
                     fatal("example compile crashed", .{});
                 },
             }
-            if (mem.indexOf(u8, result.stderr, error_match) == null) {
+            if (mem.find(u8, result.stderr, error_match) == null) {
                 print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
                 fatal("example did not have expected runtime safety error message", .{});
             }
@@ -513,7 +513,7 @@ fn printOutput(
                         fatal("example compile crashed", .{});
                     },
                 }
-                if (mem.indexOf(u8, result.stderr, error_match) == null) {
+                if (mem.find(u8, result.stderr, error_match) == null) {
                     print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match });
                     fatal("example did not have expected compile error message", .{});
                 }
@@ -623,10 +623,10 @@ fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void {
         next_tok_is_fn = false;
 
         const token = tokenizer.next();
-        if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {
+        if (mem.find(u8, src[index..token.loc.start], "//")) |comment_start_off| {
             // render one comment
             const comment_start = index + comment_start_off;
-            const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
+            const comment_end_off = mem.find(u8, src[comment_start..token.loc.start], "\n");
             const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
 
             try writeEscapedLines(out, src[index..comment_start]);
@@ -870,13 +870,13 @@ const Code = struct {
 };
 
 fn stripManifest(source_bytes: []const u8) []const u8 {
-    const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse
+    const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
         fatal("missing manifest comment", .{});
     return source_bytes[0 .. manifest_start + 1];
 }
 
 fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
-    const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse
+    const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse
         fatal("missing manifest comment", .{});
     var it = mem.tokenizeScalar(u8, source_bytes[manifest_start..], '\n');
     const first_line = skipPrefix(it.next().?);
@@ -1104,7 +1104,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 {
 
 // Returns true if number is in slice.
 fn in(slice: []const u8, number: u8) bool {
-    return mem.indexOfScalar(u8, slice, number) != null;
+    return mem.findScalar(u8, slice, number) != null;
 }
 
 fn run(
diff --git a/tools/fetch_them_macos_headers.zig b/tools/fetch_them_macos_headers.zig
index d15bf8b7dfa9f8ccb3acbbb5d978726c16379731..d2b7dd2f933e50d25f5f46f53888abad9986c8f3 100644
--- a/tools/fetch_them_macos_headers.zig
+++ b/tools/fetch_them_macos_headers.zig
@@ -187,8 +187,8 @@ fn fetchTarget(
 
     var it = mem.splitScalar(u8, headers_list_str, '\n');
     while (it.next()) |line| {
-        if (mem.lastIndexOf(u8, line, "clang") != null) continue;
-        if (mem.lastIndexOf(u8, line, prefix[0..])) |idx| {
+        if (mem.findLast(u8, line, "clang") != null) continue;
+        if (mem.findLast(u8, line, prefix[0..])) |idx| {
             const out_rel_path = line[idx + prefix.len + 1 ..];
             const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\");
             const dirname = Dir.path.dirname(out_rel_path_stripped) orelse ".";
diff --git a/tools/incr-check.zig b/tools/incr-check.zig
index cbc1ec659409eadefd89d516c8816ed36f92d4e5..500635b24972b5a54f69a873489c130e3f39a7f0 100644
--- a/tools/incr-check.zig
+++ b/tools/incr-check.zig
@@ -450,7 +450,7 @@ const Eval = struct {
             const raw_filename = eb.nullTerminatedString(src.src_path);
             // We need to replace backslashes for consistency between platforms.
             const filename = name: {
-                if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename;
+                if (std.mem.findScalar(u8, raw_filename, '\\') == null) break :name raw_filename;
                 const copied = try eval.arena.dupe(u8, raw_filename);
                 std.mem.replaceScalar(u8, copied, '\\', '/');
                 break :name copied;
@@ -777,7 +777,7 @@ const Case = struct {
                         .backend = backend,
                     });
                 } else if (std.mem.eql(u8, key, "module")) {
-                    const split_idx = std.mem.indexOfScalar(u8, val, '=') orelse
+                    const split_idx = std.mem.findScalar(u8, val, '=') orelse
                         fatal("line {d}: module does not include file", .{line_n});
                     const name = val[0..split_idx];
                     const file = val[split_idx + 1 ..];
@@ -983,7 +983,7 @@ fn rand64(io: Io) u64 {
 fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } {
     const fatal = std.process.fatal;
 
-    const split_idx = std.mem.lastIndexOfScalar(u8, input_str, '-') orelse
+    const split_idx = std.mem.findScalarLast(u8, input_str, '-') orelse
         fatal("{s}target does not include backend", .{err_prefix});
 
     const query = input_str[0..split_idx];
diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig
index 43b81238703433538070330f5d96e3fe4a337f41..a89ec3724ee72099aabe7f5ff50e47625ec1bc75 100644
--- a/tools/update_clang_options.zig
+++ b/tools/update_clang_options.zig
@@ -599,7 +599,7 @@ const known_options = [_]KnownOpt{
 const blacklisted_options = [_][]const u8{};
 
 fn knownOption(name: []const u8) ?[]const u8 {
-    const chopped_name = if (std.mem.indexOfScalar(u8, name, '=')) |idx| name[0..idx] else name;
+    const chopped_name = if (std.mem.findScalar(u8, name, '=')) |idx| name[0..idx] else name;
     for (known_options) |item| {
         if (std.mem.eql(u8, chopped_name, item.name)) {
             return item.ident;
diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig
index 55f51ce92b4f4a36f51fd176b681487de16d1621..c39008f495d3036cc4d1f9a4b93bfa235117c58d 100644
--- a/tools/update_crc_catalog.zig
+++ b/tools/update_crc_catalog.zig
@@ -99,7 +99,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8)
 
         var it = mem.splitSequence(u8, line, "  ");
         while (it.next()) |property| {
-            const i = mem.indexOf(u8, property, "=").?;
+            const i = mem.find(u8, property, "=").?;
             const key = property[0..i];
             const value = property[i + 1 ..];
             if (mem.eql(u8, key, "width")) {
-- 
2.54.0


From 03ab50821418fac99578fd762ba1ef135671b545 Mon Sep 17 00:00:00 2001
From: Daniel Kareh 
Date: Tue, 4 Aug 2026 17:43:34 -0400
Subject: [PATCH 148/215] std.Io.Dir.path: make the behavior of `stem` match
 its documentation

---
 lib/std/fs/path.zig | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig
index ffba84b9e3f80c70fa9de109525bf8a3f3262ed2..d5b7f751acf77f6a4b98951f8039bbbf4c20b752 100644
--- a/lib/std/fs/path.zig
+++ b/lib/std/fs/path.zig
@@ -1887,8 +1887,8 @@ test extension {
 /// - "hello/world/lib"        ⇒ "lib"
 pub fn stem(path: []const u8) []const u8 {
     const filename = basename(path);
-    const index = mem.findScalarLast(u8, filename, '.') orelse return filename[0..];
-    if (index == 0) return path;
+    const index = mem.findScalarLast(u8, filename, '.') orelse return filename;
+    if (index == 0) return filename;
     return filename[0..index];
 }
 
@@ -1904,8 +1904,14 @@ test stem {
     try testStem("hello...", "hello..");
     try testStem("hello.", "hello");
     try testStem("/hello.", "hello");
+    try testStem("hello/world/.gitignore", ".gitignore");
+    try testStem("/.gitignore", ".gitignore");
     try testStem(".gitignore", ".gitignore");
+    try testStem(".gitignore/", ".gitignore");
+    try testStem("hello/world/.image.png", ".image");
+    try testStem("/.image.png", ".image");
     try testStem(".image.png", ".image");
+    try testStem(".image.png/", ".image");
     try testStem("file.ext", "file");
     try testStem("file.ext.", "file.ext");
     try testStem("a.b.c", "a.b");
-- 
2.54.0


From 01e5c1885684609d84c79135e716b33a1c3fd9a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Wed, 5 Aug 2026 10:57:04 +0200
Subject: [PATCH 149/215] ci: don't test all architectures on x86_64-freebsd

See: https://codeberg.org/ziglang/zig/issues/30932#issuecomment-18469709

These targets get built on x86_64-linux-release anyway.
---
 ci/x86_64-freebsd-debug.sh   | 8 +-------
 ci/x86_64-freebsd-release.sh | 8 +-------
 2 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/ci/x86_64-freebsd-debug.sh b/ci/x86_64-freebsd-debug.sh
index c67c7bbe4d50bdd2448a83e0479ff61b65cc5a62..5266970f1c184067753df726fd8921b87fdd76be 100755
--- a/ci/x86_64-freebsd-debug.sh
+++ b/ci/x86_64-freebsd-debug.sh
@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
 stage3-debug/bin/zig build test docs \
   --maxrss ${ZSF_MAX_RSS:-0} \
   -Dstatic-llvm \
-  -Dskip-spirv \
-  -Dskip-wasm \
-  -Dskip-linux \
-  -Dskip-netbsd \
-  -Dskip-openbsd \
-  -Dskip-windows \
-  -Dskip-darwin \
+  -Dskip-non-native \
   --search-prefix "$PREFIX" \
   --test-timeout 2m
 
diff --git a/ci/x86_64-freebsd-release.sh b/ci/x86_64-freebsd-release.sh
index 83c88ef5aae163deee3cebd40c1b2b1f01047930..9425420cc083a13cf9974640d239d2c65bf99b2f 100755
--- a/ci/x86_64-freebsd-release.sh
+++ b/ci/x86_64-freebsd-release.sh
@@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib"
 stage3-release/bin/zig build test docs \
   --maxrss ${ZSF_MAX_RSS:-0} \
   -Dstatic-llvm \
-  -Dskip-spirv \
-  -Dskip-wasm \
-  -Dskip-linux \
-  -Dskip-netbsd \
-  -Dskip-openbsd \
-  -Dskip-windows \
-  -Dskip-darwin \
+  -Dskip-non-native \
   --search-prefix "$PREFIX" \
   --test-timeout 2m
 
-- 
2.54.0


From 143767a05bae7247733b6f03b56d603080a83df7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Wed, 5 Aug 2026 13:08:30 +0200
Subject: [PATCH 150/215] std.Target: bump baseline CPU for
 powerpc64-(freebsd,linux) to pwr8

Linux and FreeBSD usage on PowerPC broadly splits into two camps:

* Old Apple/Amiga hardware
* Modern IBM POWER hardware

In the first camp, we're talking hardware like the PowerPC 970 (2002) or even
older in some cases. In the second camp, most hardware still in use today is
POWER8 (2014) or newer.

I think it's safe to say that the first camp is in the minority, especially
since the open hardware platform that Raptor Computing Systems sells is based on
POWER9, and I expect that to be more interesting to PowerPC enthusiasts
nowadays.

Also, compiler support for the old hardware is poorly maintained. IBM themselves
only seem to care to support the newer POWER processors in the Linux kernel as
well as GCC and LLVM. We keep running into LLVM bugs when targeting those older
CPUs.
---
 lib/std/Target.zig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index 29440d64af025266aa10b860ffaeb69e9917c591..6ab6f2c81b1d8de3edee4c53bd7097a3cd3ae123 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -2081,6 +2081,7 @@ pub const Cpu = struct {
                     else => generic(arch),
                 },
                 .powerpc64 => switch (os.tag) {
+                    .linux, .freebsd => &powerpc.cpu.pwr8,
                     .openbsd => &powerpc.cpu.pwr9,
                     else => generic(arch),
                 },
-- 
2.54.0


From 184234141d97f2b24f00626a3ed82cb44f4e4235 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Wed, 5 Aug 2026 13:24:32 +0200
Subject: [PATCH 151/215] behavior: disable some failing float vector
 comparison tests on powerpc64

https://github.com/llvm/llvm-project/issues/214198
---
 test/behavior/floatop.zig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig
index 583b6bf6aba3f0596a452e5f311bc1a388cd4691..73a1d8c4d4ad0e1e125fc89a40ada8286d8dfb20 100644
--- a/test/behavior/floatop.zig
+++ b/test/behavior/floatop.zig
@@ -228,7 +228,7 @@ test "vector cmp f32" {
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isArm()) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
     if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
 
     try testCmpVector(f32);
@@ -250,7 +250,7 @@ test "vector cmp f128" {
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
     if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
 
     try testCmpVector(f128);
@@ -260,7 +260,7 @@ test "vector cmp f128" {
 test "vector cmp f80/c_longdouble" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/214198
     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 
-- 
2.54.0


From c80045cbe77c9cd044ab07b189003726169e0ace Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 3 Aug 2026 18:17:09 +0200
Subject: [PATCH 152/215] c_abi: include array sentinel in length calculation

---
 src/codegen/loongarch/abi.zig |   2 +-
 src/codegen/s390x/abi.zig     |   2 +-
 src/codegen/x86_64/abi.zig    |   2 +-
 test/c_abi/cfuncs.c           | 100 ++++++++++++++++++
 test/c_abi/main.zig           | 187 ++++++++++++++++++++++++++++++++++
 5 files changed, 290 insertions(+), 3 deletions(-)

diff --git a/src/codegen/loongarch/abi.zig b/src/codegen/loongarch/abi.zig
index 09e42a7cb96731dbf0ee44b37ad74f0548a08c93..ba9b79d39d5be3d10e20176bc5574c9205df5ad7 100644
--- a/src/codegen/loongarch/abi.zig
+++ b/src/codegen/loongarch/abi.zig
@@ -95,7 +95,7 @@ const Classifier = struct {
                 var class: Class = .ignored;
                 const elem_ty = ty.childType(c.zcu);
                 const elem_class = c.classifyType(elem_ty);
-                for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| {
+                for (0..std.math.lossyCast(usize, ty.arrayLenIncludingSentinel(c.zcu))) |_| {
                     class = class.combineMember(elem_class, elem_ty);
                     if (class == .address) break;
                 }
diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig
index 7b35245fdad37be5e062bbcc873c116a78a99152..f8c7864a4a313f54085b357a93f6d943ab72524e 100644
--- a/src/codegen/s390x/abi.zig
+++ b/src/codegen/s390x/abi.zig
@@ -45,7 +45,7 @@ pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class {
             128 => return .pointer,
         },
         .pointer, .optional => return .simple,
-        .array => switch (ty.arrayLen(zcu)) {
+        .array => switch (ty.arrayLenIncludingSentinel(zcu)) {
             0 => return .none,
             1 => switch (context) {
                 .ret => {},
diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig
index 3ebad4dee2a9235f641e12be27684d247bfd2de1..471c09974d6bd29a29fb0fd37bd1b7e7612088b7 100644
--- a/src/codegen/x86_64/abi.zig
+++ b/src/codegen/x86_64/abi.zig
@@ -443,7 +443,7 @@ fn classifySystemVArray(
     const field_classes = std.mem.sliceTo(&classifySystemV(array_ty.childType(zcu), zcu, target, .other), .none);
     var byte_offset = starting_byte_offset;
     const elem_size = array_ty.childType(zcu).abiSize(zcu);
-    for (0..@intCast(array_ty.arrayLen(zcu))) |_| {
+    for (0..@intCast(array_ty.arrayLenIncludingSentinel(zcu))) |_| {
         for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class|
             result_class.* = result_class.combineSystemV(field_class);
         byte_offset += elem_size;
diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c
index b74ea9ffef180944eb00c919dd5a6513fa6d32ad..a259e23413a131b4e73b5f34329e1b2e6093f44d 100644
--- a/test/c_abi/cfuncs.c
+++ b/test/c_abi/cfuncs.c
@@ -15314,6 +15314,106 @@ void c_test_struct_array_5_f32(void) {
     zig_struct_array_5_f32((struct Struct_array_5_f32){ .a = { 6, 7, 8, 9, 10 } }, 11);
 }
 
+struct Struct_array_1_f32 zig_ret_struct_array_0_sentinel_f32(void);
+void zig_struct_array_0_sentinel_f32(struct Struct_array_1_f32, size_t);
+
+struct Struct_array_1_f32 c_ret_struct_array_0_sentinel_f32(void) {
+    return (struct Struct_array_1_f32){ .a = { 0x1e1 } };
+}
+void c_struct_array_0_sentinel_f32(struct Struct_array_1_f32 s, size_t i) {
+    assert_or_panic(s.a[0] == 0x1e1);
+    assert_or_panic(i == 2);
+}
+void c_test_struct_array_0_sentinel_f32(void) {
+    struct Struct_array_1_f32 s = zig_ret_struct_array_0_sentinel_f32();
+    assert_or_panic(s.a[0] == 0x1e1);
+    zig_struct_array_0_sentinel_f32((struct Struct_array_1_f32){ .a = { 0x1e1 } }, 1);
+}
+
+struct Struct_array_2_f32 zig_ret_struct_array_1_sentinel_f32(void);
+void zig_struct_array_1_sentinel_f32(struct Struct_array_2_f32, size_t);
+
+struct Struct_array_2_f32 c_ret_struct_array_1_sentinel_f32(void) {
+    return (struct Struct_array_2_f32){ .a = { 4, 0x1e1 } };
+}
+void c_struct_array_1_sentinel_f32(struct Struct_array_2_f32 s, size_t i) {
+    assert_or_panic(s.a[0] == 5);
+    assert_or_panic(s.a[1] == 0x1e1);
+    assert_or_panic(i == 6);
+}
+void c_test_struct_array_1_sentinel_f32(void) {
+    struct Struct_array_2_f32 s = zig_ret_struct_array_1_sentinel_f32();
+    assert_or_panic(s.a[0] == 1);
+    assert_or_panic(s.a[1] == 0x1e1);
+    zig_struct_array_1_sentinel_f32((struct Struct_array_2_f32){ .a = { 2, 0x1e1 } }, 3);
+}
+
+struct Struct_array_3_f32 zig_ret_struct_array_2_sentinel_f32(void);
+void zig_struct_array_2_sentinel_f32(struct Struct_array_3_f32, size_t);
+
+struct Struct_array_3_f32 c_ret_struct_array_2_sentinel_f32(void) {
+    return (struct Struct_array_3_f32){ .a = { 6, 7, 0x1e1 } };
+}
+void c_struct_array_2_sentinel_f32(struct Struct_array_3_f32 s, size_t i) {
+    assert_or_panic(s.a[0] == 8);
+    assert_or_panic(s.a[1] == 9);
+    assert_or_panic(s.a[2] == 0x1e1);
+    assert_or_panic(i == 10);
+}
+void c_test_struct_array_2_sentinel_f32(void) {
+    struct Struct_array_3_f32 s = zig_ret_struct_array_2_sentinel_f32();
+    assert_or_panic(s.a[0] == 1);
+    assert_or_panic(s.a[1] == 2);
+    assert_or_panic(s.a[2] == 0x1e1);
+    zig_struct_array_2_sentinel_f32((struct Struct_array_3_f32){ .a = { 3, 4, 0x1e1 } }, 5);
+}
+
+struct Struct_array_4_f32 zig_ret_struct_array_3_sentinel_f32(void);
+void zig_struct_array_3_sentinel_f32(struct Struct_array_4_f32, size_t);
+
+struct Struct_array_4_f32 c_ret_struct_array_3_sentinel_f32(void) {
+    return (struct Struct_array_4_f32){ .a = { 8, 9, 10, 0x1e1 } };
+}
+void c_struct_array_3_sentinel_f32(struct Struct_array_4_f32 s, size_t i) {
+    assert_or_panic(s.a[0] == 11);
+    assert_or_panic(s.a[1] == 12);
+    assert_or_panic(s.a[2] == 13);
+    assert_or_panic(s.a[3] == 0x1e1);
+    assert_or_panic(i == 14);
+}
+void c_test_struct_array_3_sentinel_f32(void) {
+    struct Struct_array_4_f32 s = zig_ret_struct_array_3_sentinel_f32();
+    assert_or_panic(s.a[0] == 1);
+    assert_or_panic(s.a[1] == 2);
+    assert_or_panic(s.a[2] == 3);
+    assert_or_panic(s.a[3] == 0x1e1);
+    zig_struct_array_3_sentinel_f32((struct Struct_array_4_f32){ .a = { 4, 5, 6, 0x1e1 } }, 7);
+}
+
+struct Struct_array_5_f32 zig_ret_struct_array_4_sentinel_f32(void);
+void zig_struct_array_4_sentinel_f32(struct Struct_array_5_f32, size_t);
+
+struct Struct_array_5_f32 c_ret_struct_array_4_sentinel_f32(void) {
+    return (struct Struct_array_5_f32){ .a = { 10, 11, 12, 13, 0x1e1 } };
+}
+void c_struct_array_4_sentinel_f32(struct Struct_array_5_f32 s, size_t i) {
+    assert_or_panic(s.a[0] == 14);
+    assert_or_panic(s.a[1] == 15);
+    assert_or_panic(s.a[2] == 16);
+    assert_or_panic(s.a[3] == 17);
+    assert_or_panic(s.a[4] == 0x1e1);
+    assert_or_panic(i == 18);
+}
+void c_test_struct_array_4_sentinel_f32(void) {
+    struct Struct_array_5_f32 s = zig_ret_struct_array_4_sentinel_f32();
+    assert_or_panic(s.a[0] == 1);
+    assert_or_panic(s.a[1] == 2);
+    assert_or_panic(s.a[2] == 3);
+    assert_or_panic(s.a[3] == 4);
+    assert_or_panic(s.a[4] == 0x1e1);
+    zig_struct_array_4_sentinel_f32((struct Struct_array_5_f32){ .a = { 5, 6, 7, 8, 0x1e1 } }, 9);
+}
+
 struct Struct_f32a8 {
     alignas(8) float a;
 };
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index 1fd267402d74dbb38e524c8e232240ff97ef5217..15cb889467a794aaadd7ce08eb33523b4ec65885 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -16278,6 +16278,193 @@ test "struct [5]f32" {
     c_test_struct_array_5_f32();
 }
 
+const Struct_array_0_sentinel_f32 = extern struct {
+    a: [0:0x1e1]f32,
+};
+
+export fn zig_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32 {
+    return .{ .a = .{} };
+}
+export fn zig_struct_array_0_sentinel_f32(s: Struct_array_0_sentinel_f32, i: usize) void {
+    var sentinel_index: usize = 0;
+    _ = &sentinel_index;
+    expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
+    expect(i == 1) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32;
+extern fn c_struct_array_0_sentinel_f32(Struct_array_0_sentinel_f32, usize) void;
+extern fn c_test_struct_array_0_sentinel_f32() void;
+
+test "struct [0:sentinel]f32" {
+    if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+    if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
+
+    var sentinel_index: usize = 0;
+    _ = &sentinel_index;
+    const s = c_ret_struct_array_0_sentinel_f32();
+    try expect(s.a[sentinel_index] == 0x1e1);
+    c_struct_array_0_sentinel_f32(.{ .a = .{} }, 2);
+    c_test_struct_array_0_sentinel_f32();
+}
+
+const Struct_array_1_sentinel_f32 = extern struct {
+    a: [1:0x1e1]f32,
+};
+
+export fn zig_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32 {
+    return .{ .a = .{1} };
+}
+export fn zig_struct_array_1_sentinel_f32(s: Struct_array_1_sentinel_f32, i: usize) void {
+    var sentinel_index: usize = 1;
+    _ = &sentinel_index;
+    expect(s.a[0] == 2) catch @panic("test failure");
+    expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
+    expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32;
+extern fn c_struct_array_1_sentinel_f32(Struct_array_1_sentinel_f32, usize) void;
+extern fn c_test_struct_array_1_sentinel_f32() void;
+
+test "struct [1:sentinel]f32" {
+    if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .loongarch64 and builtin.abi.float() == .hard) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
+
+    var sentinel_index: usize = 1;
+    _ = &sentinel_index;
+    const s = c_ret_struct_array_1_sentinel_f32();
+    try expect(s.a[0] == 4);
+    try expect(s.a[sentinel_index] == 0x1e1);
+    c_struct_array_1_sentinel_f32(.{ .a = .{5} }, 6);
+    c_test_struct_array_1_sentinel_f32();
+}
+
+const Struct_array_2_sentinel_f32 = extern struct {
+    a: [2:0x1e1]f32,
+};
+
+export fn zig_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32 {
+    return .{ .a = .{ 1, 2 } };
+}
+export fn zig_struct_array_2_sentinel_f32(s: Struct_array_2_sentinel_f32, i: usize) void {
+    var sentinel_index: usize = 2;
+    _ = &sentinel_index;
+    expect(s.a[0] == 3) catch @panic("test failure");
+    expect(s.a[1] == 4) catch @panic("test failure");
+    expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
+    expect(i == 5) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32;
+extern fn c_struct_array_2_sentinel_f32(Struct_array_2_sentinel_f32, usize) void;
+extern fn c_test_struct_array_2_sentinel_f32() void;
+
+test "struct [2:sentinel]f32" {
+    if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+
+    var sentinel_index: usize = 2;
+    _ = &sentinel_index;
+    const s = c_ret_struct_array_2_sentinel_f32();
+    try expect(s.a[0] == 6);
+    try expect(s.a[1] == 7);
+    try expect(s.a[sentinel_index] == 0x1e1);
+    c_struct_array_2_sentinel_f32(.{ .a = .{ 8, 9 } }, 10);
+    c_test_struct_array_2_sentinel_f32();
+}
+
+const Struct_array_3_sentinel_f32 = extern struct {
+    a: [3:0x1e1]f32,
+};
+
+export fn zig_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32 {
+    return .{ .a = .{ 1, 2, 3 } };
+}
+export fn zig_struct_array_3_sentinel_f32(s: Struct_array_3_sentinel_f32, i: usize) void {
+    var sentinel_index: usize = 3;
+    _ = &sentinel_index;
+    expect(s.a[0] == 4) catch @panic("test failure");
+    expect(s.a[1] == 5) catch @panic("test failure");
+    expect(s.a[2] == 6) catch @panic("test failure");
+    expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
+    expect(i == 7) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32;
+extern fn c_struct_array_3_sentinel_f32(Struct_array_3_sentinel_f32, usize) void;
+extern fn c_test_struct_array_3_sentinel_f32() void;
+
+test "struct [3:sentinel]f32" {
+    if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+
+    var sentinel_index: usize = 3;
+    _ = &sentinel_index;
+    const s = c_ret_struct_array_3_sentinel_f32();
+    try expect(s.a[0] == 8);
+    try expect(s.a[1] == 9);
+    try expect(s.a[2] == 10);
+    try expect(s.a[sentinel_index] == 0x1e1);
+    c_struct_array_3_sentinel_f32(.{ .a = .{ 11, 12, 13 } }, 14);
+    c_test_struct_array_3_sentinel_f32();
+}
+
+const Struct_array_4_sentinel_f32 = extern struct {
+    a: [4:0x1e1]f32,
+};
+
+export fn zig_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32 {
+    return .{ .a = .{ 1, 2, 3, 4 } };
+}
+export fn zig_struct_array_4_sentinel_f32(s: Struct_array_4_sentinel_f32, i: usize) void {
+    var sentinel_index: usize = 4;
+    _ = &sentinel_index;
+    expect(s.a[0] == 5) catch @panic("test failure");
+    expect(s.a[1] == 6) catch @panic("test failure");
+    expect(s.a[2] == 7) catch @panic("test failure");
+    expect(s.a[3] == 8) catch @panic("test failure");
+    expect(s.a[sentinel_index] == 0x1e1) catch @panic("test failure");
+    expect(i == 9) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32;
+extern fn c_struct_array_4_sentinel_f32(Struct_array_4_sentinel_f32, usize) void;
+extern fn c_test_struct_array_4_sentinel_f32() void;
+
+test "struct [4:sentinel]f32" {
+    if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+
+    var sentinel_index: usize = 4;
+    _ = &sentinel_index;
+    const s = c_ret_struct_array_4_sentinel_f32();
+    try expect(s.a[0] == 10);
+    try expect(s.a[1] == 11);
+    try expect(s.a[2] == 12);
+    try expect(s.a[3] == 13);
+    try expect(s.a[sentinel_index] == 0x1e1);
+    c_struct_array_4_sentinel_f32(.{ .a = .{ 14, 15, 16, 17 } }, 18);
+    c_test_struct_array_4_sentinel_f32();
+}
+
 const Struct_f32a8 = extern struct {
     a: f32 align(8),
 };
-- 
2.54.0


From 6f7607c8e23fd8fd5d8fdbc28b119590f092dd0b Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 3 Aug 2026 21:02:56 +0200
Subject: [PATCH 153/215] c_abi: fix struct with single scalar array element on
 wasm

---
 src/codegen/wasm/abi.zig |  7 +++++++
 test/c_abi/main.zig      | 43 +++++++++++-----------------------------
 2 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig
index 0c6afdcc500202b4b4dd4b794d28b9fdb813af70..9f0b9b6dc9ebb7715d16839a6f42fd954d7787a2 100644
--- a/src/codegen/wasm/abi.zig
+++ b/src/codegen/wasm/abi.zig
@@ -84,6 +84,13 @@ pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
                 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
                     return .indirect;
             }
+            if (field_ty.zigTypeTag(zcu) == .array) {
+                switch (field_ty.arrayLenIncludingSentinel(zcu)) {
+                    0 => unreachable,
+                    1 => return classifyTypeForLlvm(field_ty.childType(zcu), zcu),
+                    else => {},
+                }
+            }
             return classifyTypeForLlvm(field_ty, zcu);
         },
         .@"union" => {
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index 15cb889467a794aaadd7ce08eb33523b4ec65885..4cc383805d755af213f3e84a2cb5447c0a5315f1 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -16107,20 +16107,12 @@ const Struct_array_1_f32 = extern struct {
     a: [1]f32,
 };
 
-comptime {
-    skip: {
-        if (builtin.cpu.arch.isWasm()) break :skip;
-
-        _ = struct {
-            export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
-                return .{ .a = .{1} };
-            }
-            export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
-                expect(s.a[0] == 2) catch @panic("test failure");
-                expect(i == 3) catch @panic("test failure");
-            }
-        };
-    }
+export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 {
+    return .{ .a = .{1} };
+}
+export fn zig_struct_array_1_f32(s: Struct_array_1_f32, i: usize) void {
+    expect(s.a[0] == 2) catch @panic("test failure");
+    expect(i == 3) catch @panic("test failure");
 }
 
 extern fn c_ret_struct_array_1_f32() Struct_array_1_f32;
@@ -16134,7 +16126,6 @@ test "struct [1]f32" {
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
     if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-    if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
 
     const s = c_ret_struct_array_1_f32();
     try expect(s.a[0] == 4);
@@ -16303,7 +16294,6 @@ test "struct [0:sentinel]f32" {
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
     if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-    if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
 
     var sentinel_index: usize = 0;
     _ = &sentinel_index;
@@ -16766,20 +16756,12 @@ const Struct_array_1_f64 = extern struct {
     a: [1]f64,
 };
 
-comptime {
-    skip: {
-        if (builtin.cpu.arch.isWasm()) break :skip;
-
-        _ = struct {
-            export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
-                return .{ .a = .{1} };
-            }
-            export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
-                expect(s.a[0] == 2) catch @panic("test failure");
-                expect(i == 3) catch @panic("test failure");
-            }
-        };
-    }
+export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 {
+    return .{ .a = .{1} };
+}
+export fn zig_struct_array_1_f64(s: Struct_array_1_f64, i: usize) void {
+    expect(s.a[0] == 2) catch @panic("test failure");
+    expect(i == 3) catch @panic("test failure");
 }
 
 extern fn c_ret_struct_array_1_f64() Struct_array_1_f64;
@@ -16793,7 +16775,6 @@ test "struct [1]f64" {
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
     if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
-    if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
 
     const s = c_ret_struct_array_1_f64();
     try expect(s.a[0] == 4);
-- 
2.54.0


From 0bebd6108e586c5b6e216b4e69c1a06aa07d411d Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Tue, 4 Aug 2026 01:08:16 +0200
Subject: [PATCH 154/215] c_abi: fix union with single scalar array element on
 wasm

---
 src/codegen/wasm/abi.zig |  7 +++++++
 test/c_abi/cfuncs.c      | 20 ++++++++++++++++++++
 test/c_abi/main.zig      | 30 ++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig
index 9f0b9b6dc9ebb7715d16839a6f42fd954d7787a2..5c88caddb98a35c6f192c647fb5d53eb032375a5 100644
--- a/src/codegen/wasm/abi.zig
+++ b/src/codegen/wasm/abi.zig
@@ -102,6 +102,13 @@ pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
             assert(layout.tag_size == 0);
             if (union_obj.field_types.len > 1) return .indirect;
             const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
+            if (first_field_ty.zigTypeTag(zcu) == .array) {
+                switch (first_field_ty.arrayLenIncludingSentinel(zcu)) {
+                    0 => unreachable,
+                    1 => return classifyTypeForLlvm(first_field_ty.childType(zcu), zcu),
+                    else => {},
+                }
+            }
             return classifyTypeForLlvm(first_field_ty, zcu);
         },
         .error_union,
diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c
index a259e23413a131b4e73b5f34329e1b2e6093f44d..110e5fd18dd4a5593c7004f439e85eed82c46a1d 100644
--- a/test/c_abi/cfuncs.c
+++ b/test/c_abi/cfuncs.c
@@ -15749,6 +15749,26 @@ void c_test_struct_array_5_f64(void) {
     zig_struct_array_5_f64((struct Struct_array_5_f64){ .a = { 6, 7, 8, 9, 10 } }, 11);
 }
 
+union Union_f64 {
+    double a;
+};
+
+union Union_f64 zig_ret_union_f64(void);
+void zig_union_f64(union Union_f64, size_t);
+
+union Union_f64 c_ret_union_f64(void) {
+    return (union Union_f64){ .a = 4 };
+}
+void c_union_f64(union Union_f64 s, size_t i) {
+    assert_or_panic(s.a == 5);
+    assert_or_panic(i == 6);
+}
+void c_test_union_f64(void) {
+    union Union_f64 s = zig_ret_union_f64();
+    assert_or_panic(s.a == 1);
+    zig_union_f64((union Union_f64){ .a = 2 }, 3);
+}
+
 struct Struct_u32_Union_u32_u32u32 {
     uint32_t a;
     union {
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index 4cc383805d755af213f3e84a2cb5447c0a5315f1..2286d838b86402f9e5e03c30e7db3732c2e3c3f4 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -16918,6 +16918,36 @@ test "struct [5]f64" {
     c_test_struct_array_5_f64();
 }
 
+const Union_f64 = extern union {
+    a: f64,
+};
+
+export fn zig_ret_union_f64() Union_f64 {
+    return .{ .a = 1 };
+}
+export fn zig_union_f64(s: Union_f64, i: usize) void {
+    expect(s.a == 2) catch @panic("test failure");
+    expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_union_f64() Union_f64;
+extern fn c_union_f64(Union_f64, usize) void;
+extern fn c_test_union_f64() void;
+
+test "union f64" {
+    if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
+    if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
+    if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+    const s = c_ret_union_f64();
+    try expect(s.a == 4);
+    c_union_f64(.{ .a = 5 }, 6);
+    c_test_union_f64();
+}
+
 const Struct_u32_Union_u32_u32u32 = extern struct {
     a: u32,
     b: extern union {
-- 
2.54.0


From fd13c819264007e8731fdb5ae9af211d18c70e9a Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 3 Aug 2026 21:52:28 +0200
Subject: [PATCH 155/215] c_abi: fix struct with OPV fields on wasm

---
 src/codegen/wasm/abi.zig | 36 ++++++++++++++++++++++--------------
 test/c_abi/cfuncs.c      | 16 ++++++++++++++++
 test/c_abi/main.zig      | 28 ++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig
index 5c88caddb98a35c6f192c647fb5d53eb032375a5..1952c65227e8d57b0c164a62286814265bae0e3c 100644
--- a/src/codegen/wasm/abi.zig
+++ b/src/codegen/wasm/abi.zig
@@ -71,27 +71,35 @@ pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
         },
         .@"struct" => {
             const struct_type = zcu.typeToStruct(ty).?;
-            if (struct_type.layout == .@"packed") {
-                return .{ .direct = ty };
+            switch (struct_type.layout) {
+                .auto => unreachable,
+                .@"packed" => return .{ .direct = ty },
+                .@"extern" => {},
             }
-            if (struct_type.field_types.len > 1) {
-                // The struct type is non-scalar.
-                return .indirect;
-            }
-            const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
-            const explicit_align = struct_type.field_aligns.getOrNone(ip, 0);
-            if (explicit_align != .none) {
-                if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
+            var opt_single_field_ty: ?Type = null;
+            for (struct_type.field_types.get(ip), 0..) |field_ty_index, field_index| {
+                const field_ty: Type = .fromInterned(field_ty_index);
+                if (!field_ty.hasRuntimeBits(zcu)) continue;
+
+                if (opt_single_field_ty != null) {
+                    return .indirect;
+                }
+
+                const field_align = struct_type.field_aligns.getOrNone(ip, field_index);
+                if (field_align != .none and field_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) {
                     return .indirect;
+                }
+                opt_single_field_ty = field_ty;
             }
-            if (field_ty.zigTypeTag(zcu) == .array) {
-                switch (field_ty.arrayLenIncludingSentinel(zcu)) {
+            const single_field_ty = opt_single_field_ty.?;
+            if (single_field_ty.zigTypeTag(zcu) == .array) {
+                switch (single_field_ty.arrayLenIncludingSentinel(zcu)) {
                     0 => unreachable,
-                    1 => return classifyTypeForLlvm(field_ty.childType(zcu), zcu),
+                    1 => return classifyTypeForLlvm(single_field_ty.childType(zcu), zcu),
                     else => {},
                 }
             }
-            return classifyTypeForLlvm(field_ty, zcu);
+            return classifyTypeForLlvm(single_field_ty, zcu);
         },
         .@"union" => {
             const union_obj = zcu.typeToUnion(ty).?;
diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c
index 110e5fd18dd4a5593c7004f439e85eed82c46a1d..327bc04ceb34148541b994bb894f04bea85bf210 100644
--- a/test/c_abi/cfuncs.c
+++ b/test/c_abi/cfuncs.c
@@ -15194,6 +15194,22 @@ void c_test_struct_f32_f32_f32_f32_f32(void) {
     zig_struct_f32_f32_f32_f32_f32((struct Struct_f32_f32_f32_f32_f32){ .a = 6, .b = 7, .c = 8, .d = 9, .e = 10 }, 11);
 }
 
+struct Struct_f32 zig_ret_struct_void_f32(void);
+void zig_struct_void_f32(struct Struct_f32, size_t);
+
+struct Struct_f32 c_ret_struct_void_f32(void) {
+    return (struct Struct_f32){ .a = 4 };
+}
+void c_struct_void_f32(struct Struct_f32 s, size_t i) {
+    assert_or_panic(s.a == 5);
+    assert_or_panic(i == 6);
+}
+void c_test_struct_void_f32(void) {
+    struct Struct_f32 s = zig_ret_struct_void_f32();
+    assert_or_panic(s.a == 1);
+    zig_struct_void_f32((struct Struct_f32){ .a = 2 }, 3);
+}
+
 struct Struct_array_1_f32 {
     float a[1];
 };
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index 2286d838b86402f9e5e03c30e7db3732c2e3c3f4..53e3890f31fa28014d84fc96012d21dbda3699dd 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -16103,6 +16103,34 @@ test "struct f32, f32, f32, f32, f32" {
     c_test_struct_f32_f32_f32_f32_f32();
 }
 
+const Struct_void_f32 = extern struct {
+    _: void = {},
+    a: f32,
+};
+
+export fn zig_ret_struct_void_f32() Struct_void_f32 {
+    return .{ .a = 1 };
+}
+export fn zig_struct_void_f32(s: Struct_void_f32, i: usize) void {
+    expect(s.a == 2) catch @panic("test failure");
+    expect(i == 3) catch @panic("test failure");
+}
+
+extern fn c_ret_struct_void_f32() Struct_void_f32;
+extern fn c_struct_void_f32(Struct_void_f32, usize) void;
+extern fn c_test_struct_void_f32() void;
+
+test "struct void, f32" {
+    if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
+    if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
+    if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest;
+
+    const s = c_ret_struct_void_f32();
+    try expect(s.a == 4);
+    c_struct_void_f32(.{ .a = 5 }, 6);
+    c_test_struct_void_f32();
+}
+
 const Struct_array_1_f32 = extern struct {
     a: [1]f32,
 };
-- 
2.54.0


From 46f98e366b10e1db59ca776c8cefcf827a66ffde Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 3 Aug 2026 22:02:28 +0200
Subject: [PATCH 156/215] c_abi: fix single element array on s390x

---
 src/codegen/s390x/abi.zig | 9 +--------
 test/c_abi/main.zig       | 3 ---
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/src/codegen/s390x/abi.zig b/src/codegen/s390x/abi.zig
index f8c7864a4a313f54085b357a93f6d943ab72524e..2c3051ffc3139a314cedadf9ec98027d846a7dd3 100644
--- a/src/codegen/s390x/abi.zig
+++ b/src/codegen/s390x/abi.zig
@@ -45,14 +45,7 @@ pub fn classifyType(ty: Type, context: Context, zcu: *Zcu) Class {
             128 => return .pointer,
         },
         .pointer, .optional => return .simple,
-        .array => switch (ty.arrayLenIncludingSentinel(zcu)) {
-            0 => return .none,
-            1 => switch (context) {
-                .ret => {},
-                .arg => return classifyType(ty.childType(zcu), context, zcu),
-            },
-            else => {},
-        },
+        .array => {},
         .@"struct", .@"union" => |tag| switch (ty.containerLayout(zcu)) {
             .auto => unreachable,
             .@"extern" => switch (context) {
diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig
index 53e3890f31fa28014d84fc96012d21dbda3699dd..a481a015117276e8abf7c4393f6d85cf60dd20fb 100644
--- a/test/c_abi/main.zig
+++ b/test/c_abi/main.zig
@@ -16153,7 +16153,6 @@ test "struct [1]f32" {
     if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
-    if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
 
     const s = c_ret_struct_array_1_f32();
     try expect(s.a[0] == 4);
@@ -16321,7 +16320,6 @@ test "struct [0:sentinel]f32" {
     if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
-    if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
 
     var sentinel_index: usize = 0;
     _ = &sentinel_index;
@@ -16802,7 +16800,6 @@ test "struct [1]f64" {
     if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
     if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
     if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
-    if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
 
     const s = c_ret_struct_array_1_f64();
     try expect(s.a[0] == 4);
-- 
2.54.0


From a06534d73a86d44b7170f56c1e4709a5eb18f681 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Tue, 4 Aug 2026 17:31:16 -0700
Subject: [PATCH 157/215] compiler: eliminate ZIG_DEBUG_MAKER

Just use ZIG_DEBUG_CMD the same as the other jit commands. Originally
this was working around a CI issue but that is no longer the case.
ZIG_DEBUG_MAKER is a new env var that didn't make it to any release tag
yet. Let's revert it to keep number of env vars more minimal.
---
 ci/x86_64-linux-debug.sh | 2 +-
 lib/std/zig.zig          | 1 -
 src/main.zig             | 4 +---
 3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh
index 0316d3bef37f4058d256c97b62ae0e212160aead..91f6291d90b345139f394f4ee0c26bbe80a5ac57 100755
--- a/ci/x86_64-linux-debug.sh
+++ b/ci/x86_64-linux-debug.sh
@@ -44,7 +44,7 @@ ninja install
 
 # Must be done after zig cc is finished.
 export ZIG_LIB_DIR="$PWD/../lib"
-export ZIG_DEBUG_MAKER=1
+export ZIG_DEBUG_CMD=1
 
 # simultaneously test building self-hosted without LLVM and with 32-bit arm
 stage3-debug/bin/zig build \
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
index 332e0114b02c3cf9747c0d3bba2021eb1b15befd..ec6fc7d630a92133751c8ae481ff193d3fc0dfff 100644
--- a/lib/std/zig.zig
+++ b/lib/std/zig.zig
@@ -767,7 +767,6 @@ pub const EnvVar = enum {
     ZIG_VERBOSE_CC,
     ZIG_VERBOSE_CMD,
     ZIG_DEBUG_CMD,
-    ZIG_DEBUG_MAKER,
     ZIG_IS_DETECTING_LIBC_PATHS,
     ZIG_IS_AVOIDING_CALLING_ITSELF,
 
diff --git a/src/main.zig b/src/main.zig
index ff915761b592ad2a1f9a6fc66336b26e9b43bc16..4ef9537109d9adf1f09048d8e7f28f5aa2780d9b 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -359,7 +359,6 @@ fn mainArgs(
                 .prepend_global_cache_path = true,
                 .prepend_zig_exe_path = true,
                 .prepend_seed = true,
-                .debug_env_var = .ZIG_DEBUG_MAKER,
                 .release_mode = .safe,
             });
         },
@@ -4863,7 +4862,6 @@ const JitCmdOptions = struct {
     capture: ?*[]u8 = null,
     /// Send error bundles via std.zig.Server over stdout
     server: bool = false,
-    debug_env_var: EnvVar = .ZIG_DEBUG_CMD,
     release_mode: std.lang.Optimize = .fast,
 };
 
@@ -4915,7 +4913,7 @@ fn jitCmdInner(
     const self_exe_path = process.executablePathAlloc(io, arena) catch |err|
         fatal("unable to find self exe path: {t}", .{err});
 
-    const optimize_mode: std.lang.Optimize = if (options.debug_env_var.isSet(environ_map))
+    const optimize_mode: std.lang.Optimize = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map))
         .debug
     else
         options.release_mode;
-- 
2.54.0


From 1b71e6e295eb7dbf367fc3c6e9f745145a28f85b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=CE=88=CE=BB=CE=BB=CE=B5=CE=BD=20=CE=95=CE=BC=CE=AF=CE=BB?=
 =?UTF-8?q?=CE=B9=CE=B1=20=CE=86=CE=BD=CE=BD=CE=B1=20Zscheile?=
 
Date: Tue, 4 Aug 2026 23:20:06 +0200
Subject: [PATCH 158/215] std.c.SIG: fix already taken tag value on Illumos

---
 lib/std/c.zig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/c.zig b/lib/std/c.zig
index 9f0feda6b37e4146bcebbdf26bdb97aefb4e7508..f45a42b6c2a5fe8d15959898075e0b6434783d54 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -2821,13 +2821,14 @@ pub const SIG = switch (native_os) {
         }
 
         pub const POLL: SIG = .IO;
+        pub const IOT: SIG = .ABRT;
+        pub const CLD: SIG = .CHLD;
 
         HUP = 1,
         INT = 2,
         QUIT = 3,
         ILL = 4,
         TRAP = 5,
-        IOT = 6,
         ABRT = 6,
         EMT = 7,
         FPE = 8,
@@ -2840,7 +2841,6 @@ pub const SIG = switch (native_os) {
         TERM = 15,
         USR1 = 16,
         USR2 = 17,
-        CLD = 18,
         CHLD = 18,
         PWR = 19,
         WINCH = 20,
-- 
2.54.0


From adba29b342cf619dc1fd4ee20d450aeb902b35d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Wed, 5 Aug 2026 19:15:23 +0200
Subject: [PATCH 159/215] ci: temporarily raise x86_64-freebsd timeout to 24h

I need to debug the build system hangs that sometimes occur in CI; this should
give me plenty of time to notice and attach a debugger.
---
 .forgejo/workflows/ci.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml
index de5070160d7a9a3554fd80e59cb07fe32a08c124..a07fdd57aeaec23a8f7b33ece4332f23bfedd4f9 100644
--- a/.forgejo/workflows/ci.yaml
+++ b/.forgejo/workflows/ci.yaml
@@ -174,7 +174,7 @@ jobs:
           fetch-depth: 0
       - name: Build and Test
         run: sh ci/x86_64-freebsd-debug.sh
-        timeout-minutes: 120
+        timeout-minutes: 1440
   x86_64-freebsd-release:
     runs-on: [self-hosted, x86_64-freebsd]
     steps:
@@ -184,7 +184,7 @@ jobs:
           fetch-depth: 0
       - name: Build and Test
         run: sh ci/x86_64-freebsd-release.sh
-        timeout-minutes: 120
+        timeout-minutes: 1440
 
   x86_64-linux-debug:
     runs-on: [self-hosted, x86_64-linux]
-- 
2.54.0


From 800fc5d25a5ed386910dc36c81ae200a19a1d01b Mon Sep 17 00:00:00 2001
From: hemisputnik 
Date: Wed, 5 Aug 2026 06:50:26 +0300
Subject: [PATCH 160/215] std.Build.Configuration: use inline else to simplify
 long switches

---
 lib/std/Build/Configuration.zig | 323 ++------------------------------
 1 file changed, 12 insertions(+), 311 deletions(-)

diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index 5743d9800ced11e00ff61ce5a122c6c5bca83b3f..3b0e6c2e7f7ee9e95bae247bb8e952850f4d9e7a 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -2120,27 +2120,18 @@ pub const OptionalCSourceLanguage = enum(u3) {
     objective_cpp,
     assembly,
     assembly_with_preprocessor,
+
     default,
 
     pub fn init(x: ?std.Build.Module.CSourceLanguage) @This() {
         return switch (x orelse return .default) {
-            .c => .c,
-            .cpp => .cpp,
-            .objective_c => .objective_c,
-            .objective_cpp => .objective_cpp,
-            .assembly => .assembly,
-            .assembly_with_preprocessor => .assembly_with_preprocessor,
+            inline else => |tag| @field(@This(), @tagName(tag)),
         };
     }
 
     pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {
         return switch (this) {
-            .c => .c,
-            .cpp => .cpp,
-            .objective_c => .objective_c,
-            .objective_cpp => .objective_cpp,
-            .assembly => .assembly,
-            .assembly_with_preprocessor => .assembly_with_preprocessor,
+            inline else => |tag| @field(std.Build.Module.CSourceLanguage, @tagName(tag)),
             .default => null,
         };
     }
@@ -2268,10 +2259,7 @@ pub const TargetQuery = struct {
 
         pub fn init(x: std.Target.Query.CpuModel) @This() {
             return switch (x) {
-                .native => .native,
-                .baseline => .baseline,
-                .determined_by_arch_os => .determined_by_arch_os,
-                .explicit => .explicit,
+                inline else => |_, tag| @field(@This(), @tagName(tag)),
             };
         }
     };
@@ -2329,71 +2317,13 @@ pub const TargetQuery = struct {
 
         pub fn init(x: ?std.Target.Abi) @This() {
             return switch (x orelse return .default) {
-                .none => .none,
-                .gnu => .gnu,
-                .gnuabin32 => .gnuabin32,
-                .gnuabi64 => .gnuabi64,
-                .gnueabi => .gnueabi,
-                .gnueabihf => .gnueabihf,
-                .gnuf32 => .gnuf32,
-                .gnusf => .gnusf,
-                .gnux32 => .gnux32,
-                .eabi => .eabi,
-                .eabihf => .eabihf,
-                .abin32 => .abin32,
-                .x32 => .x32,
-                .ilp32 => .ilp32,
-                .android => .android,
-                .androideabi => .androideabi,
-                .musl => .musl,
-                .muslabin32 => .muslabin32,
-                .muslabi64 => .muslabi64,
-                .musleabi => .musleabi,
-                .musleabihf => .musleabihf,
-                .muslf32 => .muslf32,
-                .muslsf => .muslsf,
-                .muslx32 => .muslx32,
-                .msvc => .msvc,
-                .itanium => .itanium,
-                .simulator => .simulator,
-                .ohos => .ohos,
-                .ohoseabi => .ohoseabi,
-                .call0 => .call0,
+                inline else => |tag| @field(@This(), @tagName(tag)),
             };
         }
 
         pub fn unwrap(this: @This()) ?std.Target.Abi {
             return switch (this) {
-                .none => .none,
-                .gnu => .gnu,
-                .gnuabin32 => .gnuabin32,
-                .gnuabi64 => .gnuabi64,
-                .gnueabi => .gnueabi,
-                .gnueabihf => .gnueabihf,
-                .gnuf32 => .gnuf32,
-                .gnusf => .gnusf,
-                .gnux32 => .gnux32,
-                .eabi => .eabi,
-                .eabihf => .eabihf,
-                .abin32 => .abin32,
-                .x32 => .x32,
-                .ilp32 => .ilp32,
-                .android => .android,
-                .androideabi => .androideabi,
-                .musl => .musl,
-                .muslabin32 => .muslabin32,
-                .muslabi64 => .muslabi64,
-                .musleabi => .musleabi,
-                .musleabihf => .musleabihf,
-                .muslf32 => .muslf32,
-                .muslsf => .muslsf,
-                .muslx32 => .muslx32,
-                .msvc => .msvc,
-                .itanium => .itanium,
-                .simulator => .simulator,
-                .ohos => .ohos,
-                .ohoseabi => .ohoseabi,
-                .call0 => .call0,
+                inline else => |tag| @field(std.Target.Abi, @tagName(tag)),
                 .default => null,
             };
         }
@@ -2465,132 +2395,13 @@ pub const TargetQuery = struct {
 
         pub fn init(x: ?std.Target.Cpu.Arch) @This() {
             return switch (x orelse return .default) {
-                .aarch64 => .aarch64,
-                .aarch64_be => .aarch64_be,
-                .alpha => .alpha,
-                .amdgcn => .amdgcn,
-                .arc => .arc,
-                .arceb => .arceb,
-                .arm => .arm,
-                .armeb => .armeb,
-                .avr => .avr,
-                .bpfeb => .bpfeb,
-                .bpfel => .bpfel,
-                .csky => .csky,
-                .ez80 => .ez80,
-                .hexagon => .hexagon,
-                .hppa => .hppa,
-                .hppa64 => .hppa64,
-                .kalimba => .kalimba,
-                .kvx => .kvx,
-                .lanai => .lanai,
-                .loongarch32 => .loongarch32,
-                .loongarch64 => .loongarch64,
-                .m68k => .m68k,
-                .m88k => .m88k,
-                .microblaze => .microblaze,
-                .microblazeel => .microblazeel,
-                .mips => .mips,
-                .mipsel => .mipsel,
-                .mips64 => .mips64,
-                .mips64el => .mips64el,
-                .msp430 => .msp430,
-                .nvptx => .nvptx,
-                .nvptx64 => .nvptx64,
-                .or1k => .or1k,
-                .powerpc => .powerpc,
-                .powerpcle => .powerpcle,
-                .powerpc64 => .powerpc64,
-                .powerpc64le => .powerpc64le,
-                .propeller => .propeller,
-                .riscv32 => .riscv32,
-                .riscv32be => .riscv32be,
-                .riscv64 => .riscv64,
-                .riscv64be => .riscv64be,
-                .s390x => .s390x,
-                .sh => .sh,
-                .sheb => .sheb,
-                .sparc => .sparc,
-                .sparc64 => .sparc64,
-                .spirv32 => .spirv32,
-                .spirv64 => .spirv64,
-                .thumb => .thumb,
-                .thumbeb => .thumbeb,
-                .ve => .ve,
-                .wasm32 => .wasm32,
-                .wasm64 => .wasm64,
-                .x86_16 => .x86_16,
-                .x86 => .x86,
-                .x86_64 => .x86_64,
-                .xcore => .xcore,
-                .xtensa => .xtensa,
-                .xtensaeb => .xtensaeb,
+                inline else => |tag| @field(@This(), @tagName(tag)),
             };
         }
 
         pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch {
             return switch (this) {
-                .aarch64 => .aarch64,
-                .aarch64_be => .aarch64_be,
-                .alpha => .alpha,
-                .amdgcn => .amdgcn,
-                .arc => .arc,
-                .arceb => .arceb,
-                .arm => .arm,
-                .armeb => .armeb,
-                .avr => .avr,
-                .bpfeb => .bpfeb,
-                .bpfel => .bpfel,
-                .csky => .csky,
-                .ez80 => .ez80,
-                .hexagon => .hexagon,
-                .hppa => .hppa,
-                .hppa64 => .hppa64,
-                .kalimba => .kalimba,
-                .kvx => .kvx,
-                .lanai => .lanai,
-                .loongarch32 => .loongarch32,
-                .loongarch64 => .loongarch64,
-                .m68k => .m68k,
-                .m88k => .m88k,
-                .microblaze => .microblaze,
-                .microblazeel => .microblazeel,
-                .mips => .mips,
-                .mipsel => .mipsel,
-                .mips64 => .mips64,
-                .mips64el => .mips64el,
-                .msp430 => .msp430,
-                .nvptx => .nvptx,
-                .nvptx64 => .nvptx64,
-                .or1k => .or1k,
-                .powerpc => .powerpc,
-                .powerpcle => .powerpcle,
-                .powerpc64 => .powerpc64,
-                .powerpc64le => .powerpc64le,
-                .propeller => .propeller,
-                .riscv32 => .riscv32,
-                .riscv32be => .riscv32be,
-                .riscv64 => .riscv64,
-                .riscv64be => .riscv64be,
-                .s390x => .s390x,
-                .sh => .sh,
-                .sheb => .sheb,
-                .sparc => .sparc,
-                .sparc64 => .sparc64,
-                .spirv32 => .spirv32,
-                .spirv64 => .spirv64,
-                .thumb => .thumb,
-                .thumbeb => .thumbeb,
-                .ve => .ve,
-                .wasm32 => .wasm32,
-                .wasm64 => .wasm64,
-                .x86_16 => .x86_16,
-                .x86 => .x86,
-                .x86_64 => .x86_64,
-                .xcore => .xcore,
-                .xtensa => .xtensa,
-                .xtensaeb => .xtensaeb,
-
+                inline else => |tag| @field(std.Target.Cpu.Arch, @tagName(tag)),
                 .default => null,
             };
         }
@@ -2649,106 +2460,13 @@ pub const TargetQuery = struct {
 
         pub fn init(x: ?std.Target.Os.Tag) @This() {
             return switch (x orelse return .default) {
-                .freestanding => .freestanding,
-                .other => .other,
-                .contiki => .contiki,
-                .fuchsia => .fuchsia,
-                .hermit => .hermit,
-                .managarm => .managarm,
-                .haiku => .haiku,
-                .hurd => .hurd,
-                .illumos => .illumos,
-                .linux => .linux,
-                .plan9 => .plan9,
-                .rtems => .rtems,
-                .serenity => .serenity,
-                .dragonfly => .dragonfly,
-                .freebsd => .freebsd,
-                .netbsd => .netbsd,
-                .openbsd => .openbsd,
-                .driverkit => .driverkit,
-                .ios => .ios,
-                .maccatalyst => .maccatalyst,
-                .macos => .macos,
-                .tvos => .tvos,
-                .visionos => .visionos,
-                .watchos => .watchos,
-                .windows => .windows,
-                .uefi => .uefi,
-                .@"3ds" => .@"3ds",
-                .wiiu => .wiiu,
-                .@"switch" => .@"switch",
-                .psx => .psx,
-                .ps3 => .ps3,
-                .ps4 => .ps4,
-                .ps5 => .ps5,
-                .psp => .psp,
-                .vita => .vita,
-                .emscripten => .emscripten,
-                .wasi => .wasi,
-                .amdhsa => .amdhsa,
-                .amdpal => .amdpal,
-                .cuda => .cuda,
-                .mesa3d => .mesa3d,
-                .nvcl => .nvcl,
-                .opencl => .opencl,
-                .opengl => .opengl,
-                .vulkan => .vulkan,
-                .tios => .tios,
-                .ashetos => .ashetos,
+                inline else => |tag| @field(@This(), @tagName(tag)),
             };
         }
 
         pub fn unwrap(this: @This()) ?std.Target.Os.Tag {
             return switch (this) {
-                .freestanding => .freestanding,
-                .other => .other,
-                .contiki => .contiki,
-                .fuchsia => .fuchsia,
-                .hermit => .hermit,
-                .managarm => .managarm,
-                .haiku => .haiku,
-                .hurd => .hurd,
-                .illumos => .illumos,
-                .linux => .linux,
-                .plan9 => .plan9,
-                .rtems => .rtems,
-                .serenity => .serenity,
-                .dragonfly => .dragonfly,
-                .freebsd => .freebsd,
-                .netbsd => .netbsd,
-                .openbsd => .openbsd,
-                .driverkit => .driverkit,
-                .ios => .ios,
-                .maccatalyst => .maccatalyst,
-                .macos => .macos,
-                .tvos => .tvos,
-                .visionos => .visionos,
-                .watchos => .watchos,
-                .windows => .windows,
-                .uefi => .uefi,
-                .@"3ds" => .@"3ds",
-                .wiiu => .wiiu,
-                .@"switch" => .@"switch",
-                .psx => .psx,
-                .ps3 => .ps3,
-                .ps4 => .ps4,
-                .ps5 => .ps5,
-                .psp => .psp,
-                .vita => .vita,
-                .emscripten => .emscripten,
-                .wasi => .wasi,
-                .amdhsa => .amdhsa,
-                .amdpal => .amdpal,
-                .cuda => .cuda,
-                .mesa3d => .mesa3d,
-                .nvcl => .nvcl,
-                .opencl => .opencl,
-                .opengl => .opengl,
-                .vulkan => .vulkan,
-                .tios => .tios,
-                .ashetos => .ashetos,
-
+                inline else => |tag| @field(std.Target.Os.Tag, @tagName(tag)),
                 .default => null,
             };
         }
@@ -2769,30 +2487,13 @@ pub const TargetQuery = struct {
 
         pub fn init(x: ?std.Target.ObjectFormat) @This() {
             return switch (x orelse return .default) {
-                .c => .c,
-                .coff => .coff,
-                .elf => .elf,
-                .hex => .hex,
-                .macho => .macho,
-                .plan9 => .plan9,
-                .raw => .raw,
-                .spirv => .spirv,
-                .wasm => .wasm,
+                inline else => |tag| @field(@This(), @tagName(tag)),
             };
         }
 
         pub fn unwrap(this: @This()) ?std.Target.ObjectFormat {
             return switch (this) {
-                .c => .c,
-                .coff => .coff,
-                .elf => .elf,
-                .hex => .hex,
-                .macho => .macho,
-                .plan9 => .plan9,
-                .raw => .raw,
-                .spirv => .spirv,
-                .wasm => .wasm,
-
+                inline else => |tag| @field(std.Target.ObjectFormat, @tagName(tag)),
                 .default => null,
             };
         }
-- 
2.54.0


From 11e2bb391ee13d0b91f241f9720a9ae877e5cc2a Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Mon, 13 Jul 2026 01:49:21 +0200
Subject: [PATCH 161/215] Maker: suggest --skip-oom-steps to skip memory
 limited steps

---
 lib/compiler/Maker.zig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index 1a3a37b6dc008e7c536ab91e505d7559addbc7bb..bff88d605a18cf253fc29d577e3d9349789847c3 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -2236,6 +2236,7 @@ fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void
             }
         }
         if (any_problems) {
+            log.info("use --skip-oom-steps to proceed, skipping memory limited steps", .{});
             if (maker.max_rss_is_default) {
                 log.info("use --maxrss {d} to proceed, risking system memory exhaustion", .{max_needed});
             }
-- 
2.54.0


From c9533046ca37a053f487f4002a999a29a96de517 Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Sun, 12 Jul 2026 00:53:34 -0400
Subject: [PATCH 162/215] fix: Allocator contract should allow *[len]T in more
 places

This commit continues work begun in #35222.
Although after #35222 is now legal to call `Allocator.free` on memory of
type *[len]T, code which does still does not compile. Additionally,
similarly shaped footguns remain; this commit addresses those.
---
 lib/std/mem/Allocator.zig | 48 +++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 5 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 486c69966e0e3d9bccf1b99e92d404cc36363283..e442427169f56898da818f11e3587ebe4d348dc2 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -305,6 +305,25 @@ pub fn allocBytesAligned(
     return @alignCast(byte_ptr);
 }
 
+fn SliceType(comptime Pointer: type) type {
+    const info = @typeInfo(Pointer).pointer;
+    switch (info.size) {
+        .slice => return Pointer,
+        .one => {
+            const child_info = @typeInfo(info.child);
+            comptime assert(child_info == .array);
+            const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
+            return @Pointer(
+                .slice,
+                info.attrs,
+                child_info.array.child,
+                if (sentinel_ptr) |ptr| ptr.* else null,
+            );
+        },
+        else => unreachable,
+    }
+}
+
 /// Request to modify the size of an allocation.
 ///
 /// It is guaranteed to not move the pointer, however the allocator
@@ -316,6 +335,10 @@ pub fn allocBytesAligned(
 /// `new_len` may be zero, in which case the allocation is freed.
 pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
     const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
+    if (slice_info.size != .slice) {
+        const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
+        return resize(self, slice, new_len);
+    }
     comptime assert(slice_info.size == .slice);
     const T = slice_info.child;
     if (new_len == 0) {
@@ -354,8 +377,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
 /// `new_len` may be zero, in which case the allocation is freed.
 ///
 /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
-pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) {
+pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@TypeOf(allocation)) {
     const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
+    if (slice_info.size != .slice) {
+        const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
+        return remap(self, slice, new_len);
+    }
     comptime assert(slice_info.size == .slice);
     const T = slice_info.child;
 
@@ -399,7 +426,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
 ///   do the realloc more efficiently than the caller
 /// * `resize` which returns `false` when the `Allocator` implementation cannot
 ///   change the size without relocating the allocation.
-pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) {
+pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!SliceType(@TypeOf(old_mem)) {
     return self.reallocAdvanced(old_mem, new_n, @returnAddress());
 }
 
@@ -408,8 +435,12 @@ pub fn reallocAdvanced(
     old_mem: anytype,
     new_n: usize,
     return_address: usize,
-) Error!@TypeOf(old_mem) {
+) Error!SliceType(@TypeOf(old_mem)) {
     const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
+    if (slice_info.size != .slice) {
+        const slice: SliceType(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T
+        return reallocAdvanced(self, slice, new_n, return_address);
+    }
     comptime assert(slice_info.size == .slice);
     const T = slice_info.child;
     if (old_mem.len == 0) {
@@ -446,9 +477,10 @@ pub fn reallocAdvanced(
 pub fn free(self: Allocator, memory: anytype) void {
     const slice_info = @typeInfo(@TypeOf(memory)).pointer;
     if (slice_info.size != .slice) {
-        // slicing with comptime-known start and end results in *[len]T, which may be free'd
-        comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
+        const slice: SliceType(@TypeOf(memory)) = memory; // coerce *[len]T to []T
+        return free(self, slice);
     }
+    comptime assert(slice_info.size == .slice);
     const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
     if (bytes.len == 0) return;
     @memset(bytes, undefined);
@@ -591,3 +623,9 @@ test failing {
     try std.testing.expectError(error.OutOfMemory, f.alloc(u8, std.math.maxInt(usize)));
     try std.testing.expectError(error.OutOfMemory, f.allocSentinel(u8, std.math.maxInt(usize) - 1, 0));
 }
+
+test "free single-pointer to array" {
+    const allocator = std.testing.allocator;
+    const bytes = allocator.alloc(u32, 128) catch return error.SkipZigTest;
+    allocator.free(bytes.ptr[0..128]);
+}
-- 
2.54.0


From 1e5d24a009ffef49f0888b3d6ea46aec8a82d40b Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 14:48:54 -0700
Subject: [PATCH 163/215] std: extract mem.Allocator.SliceType to meta.Slice

---
 lib/std/mem/Allocator.zig | 34 ++++++++--------------------------
 lib/std/meta.zig          | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index e442427169f56898da818f11e3587ebe4d348dc2..12d96f6030c030a11f1fd81419b6f10168b7cfa3 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -8,6 +8,7 @@ const assert = std.debug.assert;
 const math = std.math;
 const mem = std.mem;
 const Alignment = std.mem.Alignment;
+const Slice = std.meta.Slice;
 
 pub const Error = error{OutOfMemory};
 pub const Log2Align = math.Log2Int(usize);
@@ -305,25 +306,6 @@ pub fn allocBytesAligned(
     return @alignCast(byte_ptr);
 }
 
-fn SliceType(comptime Pointer: type) type {
-    const info = @typeInfo(Pointer).pointer;
-    switch (info.size) {
-        .slice => return Pointer,
-        .one => {
-            const child_info = @typeInfo(info.child);
-            comptime assert(child_info == .array);
-            const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
-            return @Pointer(
-                .slice,
-                info.attrs,
-                child_info.array.child,
-                if (sentinel_ptr) |ptr| ptr.* else null,
-            );
-        },
-        else => unreachable,
-    }
-}
-
 /// Request to modify the size of an allocation.
 ///
 /// It is guaranteed to not move the pointer, however the allocator
@@ -336,7 +318,7 @@ fn SliceType(comptime Pointer: type) type {
 pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
     const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
     if (slice_info.size != .slice) {
-        const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
+        const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
         return resize(self, slice, new_len);
     }
     comptime assert(slice_info.size == .slice);
@@ -377,10 +359,10 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
 /// `new_len` may be zero, in which case the allocation is freed.
 ///
 /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
-pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@TypeOf(allocation)) {
+pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeOf(allocation)) {
     const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
     if (slice_info.size != .slice) {
-        const slice: SliceType(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
+        const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
         return remap(self, slice, new_len);
     }
     comptime assert(slice_info.size == .slice);
@@ -426,7 +408,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?SliceType(@T
 ///   do the realloc more efficiently than the caller
 /// * `resize` which returns `false` when the `Allocator` implementation cannot
 ///   change the size without relocating the allocation.
-pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!SliceType(@TypeOf(old_mem)) {
+pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(@TypeOf(old_mem)) {
     return self.reallocAdvanced(old_mem, new_n, @returnAddress());
 }
 
@@ -435,10 +417,10 @@ pub fn reallocAdvanced(
     old_mem: anytype,
     new_n: usize,
     return_address: usize,
-) Error!SliceType(@TypeOf(old_mem)) {
+) Error!Slice(@TypeOf(old_mem)) {
     const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
     if (slice_info.size != .slice) {
-        const slice: SliceType(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T
+        const slice: Slice(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T
         return reallocAdvanced(self, slice, new_n, return_address);
     }
     comptime assert(slice_info.size == .slice);
@@ -477,7 +459,7 @@ pub fn reallocAdvanced(
 pub fn free(self: Allocator, memory: anytype) void {
     const slice_info = @typeInfo(@TypeOf(memory)).pointer;
     if (slice_info.size != .slice) {
-        const slice: SliceType(@TypeOf(memory)) = memory; // coerce *[len]T to []T
+        const slice: Slice(@TypeOf(memory)) = memory; // coerce *[len]T to []T
         return free(self, slice);
     }
     comptime assert(slice_info.size == .slice);
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index cfeb6a758524a4e0e5a3f9e6dcac57fd029123c6..76f0ae867f66dd158e30521bbd2c1e7e4ef53f9d 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -1,10 +1,9 @@
 const builtin = @import("builtin");
+
 const std = @import("std.zig");
-const debug = std.debug;
+const assert = std.debug.assert;
 const mem = std.mem;
-const math = std.math;
 const testing = std.testing;
-const root = @import("root");
 
 pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags;
 
@@ -821,8 +820,8 @@ pub fn isError(error_union: anytype) bool {
 }
 
 test isError {
-    try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));
-    try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));
+    try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0)));
+    try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5)));
 }
 
 /// Returns true if a type has a namespace and the namespace contains `name`;
@@ -1070,3 +1069,28 @@ test hasUniqueRepresentation {
 
     try testing.expect(hasUniqueRepresentation(StructWithComptimeFields));
 }
+
+/// Given a pointer type, type-erases the array length if present, returning an
+/// equivalent pointer type that is always a slice.
+pub fn Slice(comptime Pointer: type) type {
+    const info = @typeInfo(Pointer).pointer;
+    switch (info.size) {
+        .slice => return Pointer,
+        .one => {
+            const child_info = @typeInfo(info.child);
+            comptime assert(child_info == .array);
+            const sentinel_ptr: ?*const child_info.array.child = @ptrCast(@alignCast(child_info.array.sentinel_ptr));
+            return @Pointer(
+                .slice,
+                info.attrs,
+                child_info.array.child,
+                if (sentinel_ptr) |ptr| ptr.* else null,
+            );
+        },
+        else => unreachable,
+    }
+}
+
+test Slice {
+    try testing.expectEqual([]i32, Slice(*[10]i32));
+}
-- 
2.54.0


From 009604d690aeaac6957d4646a815bc8762e84757 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 15:11:22 -0700
Subject: [PATCH 164/215] Allocator: simplify; avoid unnecessary recursion

---
 lib/std/mem/Allocator.zig | 46 ++++++++++++++++-----------------------
 1 file changed, 19 insertions(+), 27 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 12d96f6030c030a11f1fd81419b6f10168b7cfa3..08bfe689ff4eca5f1b3cb434757371223cfc8916 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -316,18 +316,15 @@ pub fn allocBytesAligned(
 ///
 /// `new_len` may be zero, in which case the allocation is freed.
 pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
-    const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
-    if (slice_info.size != .slice) {
-        const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
-        return resize(self, slice, new_len);
-    }
-    comptime assert(slice_info.size == .slice);
+    const SliceType = Slice(@TypeOf(allocation));
+    const slice: SliceType = allocation; // coerce *[len]T to []T
+    const slice_info = @typeInfo(SliceType).pointer;
     const T = slice_info.child;
     if (new_len == 0) {
-        self.free(allocation);
+        self.free(slice);
         return true;
     }
-    if (allocation.len == 0) {
+    if (slice.len == 0) {
         return false;
     }
     const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
@@ -360,27 +357,24 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
 ///
 /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
 pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeOf(allocation)) {
-    const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
-    if (slice_info.size != .slice) {
-        const slice: Slice(@TypeOf(allocation)) = allocation; // coerce *[len]T to []T
-        return remap(self, slice, new_len);
-    }
-    comptime assert(slice_info.size == .slice);
+    const SliceType = Slice(@TypeOf(allocation));
+    const slice: SliceType = allocation; // coerce *[len]T to []T
+    const slice_info = @typeInfo(SliceType).pointer;
     const T = slice_info.child;
 
     if (new_len == 0) {
-        self.free(allocation);
-        return allocation[0..0];
+        self.free(slice);
+        return slice[0..0];
     }
-    if (allocation.len == 0) {
+    if (slice.len == 0) {
         return null;
     }
     if (@sizeOf(T) == 0) {
-        var new_memory = allocation;
+        var new_memory = slice;
         new_memory.len = new_len;
         return new_memory;
     }
-    const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
+    const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(slice)));
     // I would like to use saturating multiplication here, but LLVM cannot lower it
     // on WebAssembly: https://github.com/ziglang/zig/issues/9660
     //const new_len_bytes = new_len *| @sizeOf(T);
@@ -418,25 +412,23 @@ pub fn reallocAdvanced(
     new_n: usize,
     return_address: usize,
 ) Error!Slice(@TypeOf(old_mem)) {
-    const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
-    if (slice_info.size != .slice) {
-        const slice: Slice(@TypeOf(old_mem)) = old_mem; // coerce *[len]T to []T
-        return reallocAdvanced(self, slice, new_n, return_address);
-    }
+    const SliceType = Slice(@TypeOf(old_mem));
+    const slice: SliceType = old_mem; // coerce *[len]T to []T
+    const slice_info = @typeInfo(SliceType).pointer;
     comptime assert(slice_info.size == .slice);
     const T = slice_info.child;
-    if (old_mem.len == 0) {
+    if (slice.len == 0) {
         return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);
     }
     if (new_n == 0) {
-        self.free(old_mem);
+        self.free(slice);
         const alignment = slice_info.attrs.@"align" orelse @alignOf(T);
         const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment);
         const ptr: *align(alignment) [0]T = @ptrFromInt(addr);
         return ptr;
     }
 
-    const old_byte_slice: []u8 = @ptrCast(@constCast(mem.absorbSentinel(old_mem)));
+    const old_byte_slice: []u8 = @ptrCast(@constCast(mem.absorbSentinel(slice)));
     const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory;
     // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
     if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)), byte_count, return_address)) |p| {
-- 
2.54.0


From 8901bfe190e2360f934c6e4330cac5eed6c8712b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Thu, 6 Aug 2026 00:42:30 +0200
Subject: [PATCH 165/215] ci: bump s390x-linux-debug timeout by 1 hour

---
 .forgejo/workflows/ci.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml
index a07fdd57aeaec23a8f7b33ece4332f23bfedd4f9..74d401cdead06e0f9f8ee3b6f4197a9ebdec09e8 100644
--- a/.forgejo/workflows/ci.yaml
+++ b/.forgejo/workflows/ci.yaml
@@ -153,7 +153,7 @@ jobs:
           fetch-depth: 0
       - name: Build and Test
         run: sh ci/s390x-linux-debug.sh
-        timeout-minutes: 420
+        timeout-minutes: 480
   s390x-linux-release:
     runs-on: [self-hosted, s390x-linux]
     steps:
-- 
2.54.0


From 6e61a77ec80b2974961bcc460c34af3385c101a0 Mon Sep 17 00:00:00 2001
From: xtex 
Date: Sun, 22 Mar 2026 08:07:03 +0800
Subject: [PATCH 166/215] aarch64: fix Select enum where enum tag is simple
 type

Tag type can be c_int or something similiar.

Change-Id: I41a03860327774586239c5d523180d85d7cc52d7
---
 src/codegen/aarch64/Select.zig | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
index 520bad02743a1a0537226e7f40a6595046a3a42b..1e5f1cbb6e7eee1fc176bff68fa0511dd8ec1b7a 100644
--- a/src/codegen/aarch64/Select.zig
+++ b/src/codegen/aarch64/Select.zig
@@ -12176,9 +12176,7 @@ pub const CallAbiIterator = struct {
                 const loaded_struct = ip.loadStructType(ty.toIntern());
                 switch (loaded_struct.layout) {
                     .auto, .@"extern" => {},
-                    .@"packed" => continue :type_key .{
-                        .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type,
-                    },
+                    .@"packed" => continue :type_key ip.indexToKey(loaded_struct.packed_backing_int_type),
                 }
                 const size = wip_vi.size(isel);
                 if (size <= 16 * 4) homogeneous_aggregate: {
@@ -12300,9 +12298,7 @@ pub const CallAbiIterator = struct {
                 }
             },
             .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
-            .enum_type => continue :type_key .{
-                .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type,
-            },
+            .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type),
             .error_set_type,
             .inferred_error_set_type,
             => continue :type_key .{ .simple_type = .anyerror },
-- 
2.54.0


From cbf00af868e527f61ab59746ea23507a7e1e124a Mon Sep 17 00:00:00 2001
From: Techatrix 
Date: Thu, 6 Aug 2026 19:54:20 +0200
Subject: [PATCH 167/215] std.Build: remove unused libc flag from compile step

Whether libc and libcpp need to be linked is resolved on the maker side
in `Maker/Step/Compile.zig`.
---
 lib/compiler/Maker/Step/Compile.zig | 4 ++--
 lib/std/Build/Configuration.zig     | 3 +--
 lib/std/Build/Serialize.zig         | 2 --
 lib/std/Build/Step/Compile.zig      | 5 -----
 4 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig
index adf88b9f1baef3712b1d6ca707d4bed7db25e700..c487966999ca178d88b83332b0f953baa410a52e 100644
--- a/lib/compiler/Maker/Step/Compile.zig
+++ b/lib/compiler/Maker/Step/Compile.zig
@@ -215,8 +215,8 @@ fn lowerZigArgs(
     try addBool(gpa, zig_args, "-ffuzz", fuzz);
 
     {
-        var is_linking_libc = conf_comp.flags3.is_linking_libc;
-        var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;
+        var is_linking_libc = false;
+        var is_linking_libcpp = false;
 
         // Stores system libraries that have already been seen for at least one
         // module, along with any C compiler arguments that need to be passed
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index 5743d9800ced11e00ff61ce5a122c6c5bca83b3f..8337da6d2f9d44f6f3b0a96241b4478f55afe3b0 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -984,8 +984,6 @@ pub const Step = extern struct {
         };
 
         pub const Flags3 = packed struct(u32) {
-            is_linking_libc: bool,
-            is_linking_libcpp: bool,
             version: bool,
             initial_memory: bool,
             max_memory: bool,
@@ -1003,6 +1001,7 @@ pub const Step = extern struct {
             entry: Entry,
             lto: Lto,
             subsystem: Subsystem,
+            _: u2 = 0,
         };
 
         pub const Flags4 = packed struct(u32) {
diff --git a/lib/std/Build/Serialize.zig b/lib/std/Build/Serialize.zig
index 72355264d978c15b712d92242df14f0c92eb4b6f..c3e9443181565196d6d922ea97f6e94f386b0f8a 100644
--- a/lib/std/Build/Serialize.zig
+++ b/lib/std/Build/Serialize.zig
@@ -168,8 +168,6 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
                                 .linkage = .init(c.linkage),
                             },
                             .flags3 = .{
-                                .is_linking_libc = c.is_linking_libc,
-                                .is_linking_libcpp = c.is_linking_libcpp,
                                 .version = c.version != null,
                                 .compress_debug_sections = c.compress_debug_sections,
                                 .initial_memory = c.initial_memory != null,
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 0f7cdbc405d74778a28e370c477dcb5b58ca1e8c..df4da47b01df0ae1bdb0ad19e090437f96063bb7 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -220,11 +220,6 @@ expect_errors: ?ExpectedCompileErrors = null,
 /// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.
 error_limit: ?u32 = null,
 
-/// Computed during make().
-is_linking_libc: bool = false,
-/// Computed during make().
-is_linking_libcpp: bool = false,
-
 /// Enables coverage instrumentation that is only useful if you are using third
 /// party fuzzers that depend on it. Otherwise, slows down the instrumented
 /// binary with unnecessary function calls.
-- 
2.54.0


From b470382173c6be27f6cdd46c3adce0e59f2b3675 Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Thu, 6 Aug 2026 20:35:17 -0400
Subject: [PATCH 168/215] feat(mem): allow absorbSentinel on *[n]T

---
 lib/std/mem.zig           | 38 +++++++++++------
 lib/std/mem/Allocator.zig | 90 +++++++++++++++++++++++++--------------
 lib/std/meta.zig          | 22 ++++++++++
 3 files changed, 107 insertions(+), 43 deletions(-)

diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 55b9019c4f4d95cfce0f271de52d12a856f9aea8..f6b2af68f914e5d31da6fc89f3702567d99fc1ac 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -9,6 +9,7 @@ const assert = debug.assert;
 const math = std.math;
 const testing = std.testing;
 const Endian = std.lang.Endian;
+const AbsorbSentinel = std.meta.AbsorbSentinel;
 
 /// The standard library currently thoroughly depends on byte size
 /// being 8 bits.  (see the use of u8 throughout allocation code as
@@ -4738,22 +4739,28 @@ test "sliceAsBytes preserves pointer attributes" {
     try testing.expectEqual(in_attrs.@"align", out_attrs.@"align");
 }
 
-fn AbsorbSentinelReturnType(comptime Slice: type) type {
-    const info = @typeInfo(Slice).pointer;
-    assert(info.size == .slice);
-    return @Pointer(.slice, info.attrs, info.child, null);
-}
-
 /// If the provided slice is not sentinel terminated, do nothing and return that slice.
 /// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
 /// length increased by one to include the absorbed sentinel element.
-pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) {
+pub fn absorbSentinel(slice: anytype) AbsorbSentinel(@TypeOf(slice)) {
     const info = @typeInfo(@TypeOf(slice)).pointer;
-    comptime assert(info.size == .slice);
-    if (info.sentinel_ptr == null) {
-        return slice;
-    } else {
-        return slice.ptr[0 .. slice.len + 1];
+    switch (info.size) {
+        .slice => {
+            if (info.sentinel_ptr == null) {
+                return slice;
+            } else {
+                return slice.ptr[0 .. slice.len + 1];
+            }
+        },
+        .one => {
+            const child_info = @typeInfo(info.child).array;
+            if (child_info.sentinel_ptr == null) {
+                return slice;
+            } else {
+                return slice[0 .. child_info.len + 1];
+            }
+        },
+        else => unreachable,
     }
 }
 
@@ -4762,21 +4769,28 @@ test absorbSentinel {
         var buffer: [3:0]u8 = .{ 1, 2, 3 };
         const foo: [:0]const u8 = &buffer;
         const bar: []const u8 = &buffer;
+        const baz: *const [3:0]u8 = &buffer;
         try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));
         try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));
+        try testing.expectEqual(*const [4]u8, @TypeOf(absorbSentinel(baz)));
         try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));
         try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));
+        try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(baz));
     }
     {
         var buffer: [3:0]u8 = .{ 1, 2, 3 };
         const foo: [:0]u8 = &buffer;
         const bar: []u8 = &buffer;
+        const baz: *[3:0]u8 = &buffer;
         try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));
         try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));
+        try testing.expectEqual(*[4]u8, @TypeOf(absorbSentinel(baz)));
         var expected_foo = [_]u8{ 1, 2, 3, 0 };
         try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));
         var expected_bar = [_]u8{ 1, 2, 3 };
         try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar));
+        var expected_baz = [_]u8{ 1, 2, 3, 0 };
+        try testing.expectEqualSlices(u8, &expected_baz, absorbSentinel(baz));
     }
 }
 
diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 08bfe689ff4eca5f1b3cb434757371223cfc8916..f16944bb7a934071acb8c89808f1560c2e08df9c 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -9,6 +9,7 @@ const math = std.math;
 const mem = std.mem;
 const Alignment = std.mem.Alignment;
 const Slice = std.meta.Slice;
+const AbsorbSentinel = std.meta.AbsorbSentinel;
 
 pub const Error = error{OutOfMemory};
 pub const Log2Align = math.Log2Int(usize);
@@ -316,15 +317,16 @@ pub fn allocBytesAligned(
 ///
 /// `new_len` may be zero, in which case the allocation is freed.
 pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
-    const SliceType = Slice(@TypeOf(allocation));
-    const slice: SliceType = allocation; // coerce *[len]T to []T
-    const slice_info = @typeInfo(SliceType).pointer;
-    const T = slice_info.child;
+    const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
+    const T = if (slice_info.size != .slice) comptime T: {
+        assert(slice_info.size == .one);
+        break :T @typeInfo(slice_info.child).array.child;
+    } else slice_info.child;
     if (new_len == 0) {
-        self.free(slice);
+        self.free(allocation);
         return true;
     }
-    if (slice.len == 0) {
+    if (allocation.len == 0) {
         return false;
     }
     const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
@@ -356,25 +358,26 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
 /// `new_len` may be zero, in which case the allocation is freed.
 ///
 /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`.
-pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeOf(allocation)) {
-    const SliceType = Slice(@TypeOf(allocation));
-    const slice: SliceType = allocation; // coerce *[len]T to []T
-    const slice_info = @typeInfo(SliceType).pointer;
-    const T = slice_info.child;
+pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(AbsorbSentinel(@TypeOf(allocation))) {
+    const slice_info = @typeInfo(@TypeOf(allocation)).pointer;
+    const T = if (slice_info.size != .slice) comptime T: {
+        assert(slice_info.size == .one);
+        break :T @typeInfo(slice_info.child).array.child;
+    } else slice_info.child;
 
     if (new_len == 0) {
-        self.free(slice);
-        return slice[0..0];
+        self.free(allocation);
+        return allocation[0..0];
     }
-    if (slice.len == 0) {
+    if (allocation.len == 0) {
         return null;
     }
     if (@sizeOf(T) == 0) {
-        var new_memory = slice;
+        var new_memory = allocation;
         new_memory.len = new_len;
         return new_memory;
     }
-    const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(slice)));
+    const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
     // I would like to use saturating multiplication here, but LLVM cannot lower it
     // on WebAssembly: https://github.com/ziglang/zig/issues/9660
     //const new_len_bytes = new_len *| @sizeOf(T);
@@ -402,7 +405,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(@TypeO
 ///   do the realloc more efficiently than the caller
 /// * `resize` which returns `false` when the `Allocator` implementation cannot
 ///   change the size without relocating the allocation.
-pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(@TypeOf(old_mem)) {
+pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) {
     return self.reallocAdvanced(old_mem, new_n, @returnAddress());
 }
 
@@ -411,24 +414,24 @@ pub fn reallocAdvanced(
     old_mem: anytype,
     new_n: usize,
     return_address: usize,
-) Error!Slice(@TypeOf(old_mem)) {
-    const SliceType = Slice(@TypeOf(old_mem));
-    const slice: SliceType = old_mem; // coerce *[len]T to []T
-    const slice_info = @typeInfo(SliceType).pointer;
-    comptime assert(slice_info.size == .slice);
-    const T = slice_info.child;
-    if (slice.len == 0) {
+) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) {
+    const slice_info = @typeInfo(@TypeOf(old_mem)).pointer;
+    const T = if (slice_info.size != .slice) comptime T: {
+        assert(slice_info.size == .one);
+        break :T @typeInfo(slice_info.child).array.child;
+    } else slice_info.child;
+    if (old_mem.len == 0) {
         return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address);
     }
     if (new_n == 0) {
-        self.free(slice);
+        self.free(old_mem);
         const alignment = slice_info.attrs.@"align" orelse @alignOf(T);
         const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment);
         const ptr: *align(alignment) [0]T = @ptrFromInt(addr);
         return ptr;
     }
 
-    const old_byte_slice: []u8 = @ptrCast(@constCast(mem.absorbSentinel(slice)));
+    const old_byte_slice: []u8 = @ptrCast(@constCast(mem.absorbSentinel(old_mem)));
     const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory;
     // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
     if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.attrs.@"align" orelse @alignOf(T)), byte_count, return_address)) |p| {
@@ -451,10 +454,8 @@ pub fn reallocAdvanced(
 pub fn free(self: Allocator, memory: anytype) void {
     const slice_info = @typeInfo(@TypeOf(memory)).pointer;
     if (slice_info.size != .slice) {
-        const slice: Slice(@TypeOf(memory)) = memory; // coerce *[len]T to []T
-        return free(self, slice);
+        assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
     }
-    comptime assert(slice_info.size == .slice);
     const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
     if (bytes.len == 0) return;
     @memset(bytes, undefined);
@@ -600,6 +601,33 @@ test failing {
 
 test "free single-pointer to array" {
     const allocator = std.testing.allocator;
-    const bytes = allocator.alloc(u32, 128) catch return error.SkipZigTest;
-    allocator.free(bytes.ptr[0..128]);
+    {
+        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
+        slice[127] = 0;
+        const ptr = slice[0..127 :0];
+        allocator.free(ptr);
+    }
+    {
+        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
+        slice[127] = 0;
+        const ptr = slice[0..127 :0];
+        if (allocator.resize(ptr, 16)) {
+            allocator.free(ptr[0..16]);
+        } else allocator.free(ptr);
+    }
+    {
+        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
+        slice[127] = 0;
+        const ptr = slice[0..127 :0];
+        if (allocator.remap(ptr, 16)) |new| {
+            allocator.free(new);
+        } else allocator.free(ptr);
+    }
+    {
+        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
+        slice[127] = 0;
+        const ptr = slice[0..127 :0];
+        const new = allocator.realloc(ptr, 16) catch return error.SkipZigTest;
+        allocator.free(new);
+    }
 }
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 76f0ae867f66dd158e30521bbd2c1e7e4ef53f9d..edc4a5c4e8eca6de0891b5435e644f0917a1ed28 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -1091,6 +1091,28 @@ pub fn Slice(comptime Pointer: type) type {
     }
 }
 
+/// Given a pointer type, removes the sentinel if present, returning an
+/// equivalent pointer type with no sentinel
+pub fn AbsorbSentinel(comptime Pointer: type) type {
+    const info = @typeInfo(Pointer).pointer;
+    switch (info.size) {
+        .slice => return @Pointer(.slice, info.attrs, info.child, null),
+        .one => {
+            const child_info = @typeInfo(info.child).array;
+            if (child_info.sentinel_ptr == null) {
+                return Pointer;
+            } else {
+                return @Pointer(.one, info.attrs, [child_info.len + 1]child_info.child, null);
+            }
+        },
+        else => unreachable,
+    }
+}
+
 test Slice {
     try testing.expectEqual([]i32, Slice(*[10]i32));
 }
+
+test AbsorbSentinel {
+    try testing.expectEqual(*[5]u32, AbsorbSentinel(*[4:0]u32));
+}
-- 
2.54.0


From 89069b54d9f3a83ac675c6a18df2c4a52d019835 Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Thu, 6 Aug 2026 22:26:40 -0400
Subject: [PATCH 169/215] fix(Allocator.free): restore compile error

---
 lib/std/mem/Allocator.zig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index f16944bb7a934071acb8c89808f1560c2e08df9c..1f11c637b0168068004019b8839458f021d679f5 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -454,7 +454,7 @@ pub fn reallocAdvanced(
 pub fn free(self: Allocator, memory: anytype) void {
     const slice_info = @typeInfo(@TypeOf(memory)).pointer;
     if (slice_info.size != .slice) {
-        assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
+        comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array);
     }
     const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory)));
     if (bytes.len == 0) return;
-- 
2.54.0


From 2b242157b875573c68e92ebe4b8dbddc7f01ffdf Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Thu, 6 Aug 2026 19:49:00 -0700
Subject: [PATCH 170/215] std.mem.Allocator: remove bitrotted comments

closes #36398
---
 lib/std/mem/Allocator.zig | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 486c69966e0e3d9bccf1b99e92d404cc36363283..9ab983f8b82c2ba60b6f5b45399b7fb8031b1336 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -326,9 +326,6 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
         return false;
     }
     const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
-    // I would like to use saturating multiplication here, but LLVM cannot lower it
-    // on WebAssembly: https://github.com/ziglang/zig/issues/9660
-    //const new_len_bytes = new_len *| @sizeOf(T);
     const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false;
     return self.rawResize(
         old_memory,
@@ -372,9 +369,6 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo
         return new_memory;
     }
     const old_memory: []u8 = @ptrCast(@constCast(mem.absorbSentinel(allocation)));
-    // I would like to use saturating multiplication here, but LLVM cannot lower it
-    // on WebAssembly: https://github.com/ziglang/zig/issues/9660
-    //const new_len_bytes = new_len *| @sizeOf(T);
     const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null;
     const new_ptr = self.rawRemap(
         old_memory,
-- 
2.54.0


From 16fbd314dc9590077267fc373b76b7c7b977977a Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Thu, 6 Aug 2026 23:44:45 -0400
Subject: [PATCH 171/215] fix(Allocator): test style fixes

---
 lib/std/mem/Allocator.zig | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 1f11c637b0168068004019b8839458f021d679f5..d50c7c1764bfe5b38a78d0761bb4983736839e41 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -602,32 +602,32 @@ test failing {
 test "free single-pointer to array" {
     const allocator = std.testing.allocator;
     {
-        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
-        slice[127] = 0;
-        const ptr = slice[0..127 :0];
+        const allocation = try allocator.alloc(u32, 128);
+        allocation[127] = 0;
+        const ptr: *[127:0]u32 = allocation[0..127 :0];
         allocator.free(ptr);
     }
     {
-        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
-        slice[127] = 0;
-        const ptr = slice[0..127 :0];
+        const allocation = try allocator.alloc(u32, 128);
+        allocation[127] = 0;
+        const ptr: *[127:0]u32 = allocation[0..127 :0];
         if (allocator.resize(ptr, 16)) {
             allocator.free(ptr[0..16]);
         } else allocator.free(ptr);
     }
     {
-        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
-        slice[127] = 0;
-        const ptr = slice[0..127 :0];
+        const allocation = try allocator.alloc(u32, 128);
+        allocation[127] = 0;
+        const ptr: *[127:0]u32 = allocation[0..127 :0];
         if (allocator.remap(ptr, 16)) |new| {
             allocator.free(new);
         } else allocator.free(ptr);
     }
     {
-        const slice = allocator.alloc(u32, 128) catch return error.SkipZigTest;
-        slice[127] = 0;
-        const ptr = slice[0..127 :0];
-        const new = allocator.realloc(ptr, 16) catch return error.SkipZigTest;
+        const allocation = try allocator.alloc(u32, 128);
+        allocation[127] = 0;
+        const ptr: *[127:0]u32 = allocation[0..127 :0];
+        const new = try allocator.realloc(ptr, 16);
         allocator.free(new);
     }
 }
-- 
2.54.0


From 21f23814383ff8060a6b983c5ff9e47b5f1853ba Mon Sep 17 00:00:00 2001
From: Saurabh Mishra 
Date: Fri, 7 Aug 2026 07:30:10 +0200
Subject: [PATCH 172/215] std.ArrayListUnmanaged: `last` and `lastPtr` methods
 (#36318)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ArrayList:

- `getLastOrNull` has been deprecated and renamed to `last`
- `getLast` has been removed in favor of `last` combined with `.?`
- `lastPtr` has been added which returns `?*T`

Upgrade guide:

```zig
if (list.getLastOrNull()) |foo| {
    // ...
}
const foo = list.getLast();
```
⬇️
```zig
if (list.last()) |foo| {
    // ...
}
const foo = list.last().?;
```

Co-authored-by: Ryan Liptak 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36318
Reviewed-by: Ryan Liptak 
---
 lib/compiler/Maker.zig                       |  2 +-
 lib/compiler/translate-c/MacroTranslator.zig |  2 +-
 lib/docs/wasm/markdown/Parser.zig            | 22 ++++++++---------
 lib/std/array_list.zig                       | 25 +++++++++++++-------
 lib/std/deque.zig                            |  2 +-
 lib/std/zig/Ast/Render.zig                   |  4 ++--
 lib/std/zig/WindowsSdk.zig                   |  8 +++----
 lib/std/zig/llvm/Builder.zig                 |  8 +++----
 src/codegen/llvm.zig                         |  2 +-
 src/codegen/spirv/CodeGen.zig                |  4 ++--
 src/codegen/x86_64/CodeGen.zig               |  4 ++--
 tools/bsp.zig                                |  2 +-
 12 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index bff88d605a18cf253fc29d577e3d9349789847c3..869471d4e921856cee4fd870c299a95aa0fd5965 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -2666,7 +2666,7 @@ fn makeStep(
             maker.available_rss += max_rss;
             dispatch_set.ensureUnusedCapacity(gpa, maker.memory_blocked_steps.items.len) catch
                 @panic("TODO eliminate memory allocation here");
-            while (maker.memory_blocked_steps.getLast()) |candidate_index| {
+            while (maker.memory_blocked_steps.last()) |candidate_index| {
                 const candidate_max_rss = candidate_index.ptr(c).max_rss.toBytes();
                 if (maker.available_rss < candidate_max_rss) break;
                 assert(maker.memory_blocked_steps.pop() == candidate_index);
diff --git a/lib/compiler/translate-c/MacroTranslator.zig b/lib/compiler/translate-c/MacroTranslator.zig
index ed4cb8a997a0d87b1bc25d63a1a0f86b6501a313..04b0e9cb3d84a0d78566470e94a7f1ca565ec8b5 100644
--- a/lib/compiler/translate-c/MacroTranslator.zig
+++ b/lib/compiler/translate-c/MacroTranslator.zig
@@ -361,7 +361,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
                 return error.ParseError;
             },
         });
-        if (bytes.getLast().? == '.') {
+        if (bytes.last().? == '.') {
             bytes.appendAssumeCapacity('0');
         } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) {
             bytes.appendSliceAssumeCapacity(".0");
diff --git a/lib/docs/wasm/markdown/Parser.zig b/lib/docs/wasm/markdown/Parser.zig
index 3721b11b373b560de6617a4905b56fa106ae6d8e..1bded7541327d17d35aef311c231d6b7171df4e5 100644
--- a/lib/docs/wasm/markdown/Parser.zig
+++ b/lib/docs/wasm/markdown/Parser.zig
@@ -209,7 +209,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
     } else p.pending_blocks.items.len;
 
     const in_code_block = p.pending_blocks.items.len > 0 and
-        p.pending_blocks.getLast().?.tag == .code_block;
+        p.pending_blocks.last().?.tag == .code_block;
     const code_block_end = in_code_block and
         first_unmatched + 1 == p.pending_blocks.items.len;
     // New blocks cannot be started if we are actively inside a code block or
@@ -225,7 +225,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
     if (maybe_block_start == null and
         !isBlank(rest_line) and
         p.pending_blocks.items.len > 0 and
-        p.pending_blocks.getLast().?.tag == .paragraph)
+        p.pending_blocks.last().?.tag == .paragraph)
     {
         try p.addScratchStringLine(mem.trimStart(u8, rest_line, " \t"));
         return;
@@ -236,7 +236,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
     // paragraphs.
     if (maybe_block_start != null and
         p.pending_blocks.items.len > 0 and
-        p.pending_blocks.getLast().?.tag == .paragraph)
+        p.pending_blocks.last().?.tag == .paragraph)
     {
         try p.closeLastBlock();
     }
@@ -259,7 +259,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
     // Do not append the end of a code block (```) as textual content.
     if (code_block_end) return;
 
-    const can_accept = if (p.pending_blocks.getLast()) |last_pending_block|
+    const can_accept = if (p.pending_blocks.last()) |last_pending_block|
         last_pending_block.canAccept()
     else
         .blocks;
@@ -273,7 +273,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void {
             // loose, since we might just be looking at a blank line after the
             // end of the last item in the list. The final determination will be
             // made when appending the next child of the list or list item.
-            const maybe_containing_list_index = if (p.pending_blocks.items.len > 0 and p.pending_blocks.getLast().?.tag == .list_item)
+            const maybe_containing_list_index = if (p.pending_blocks.items.len > 0 and p.pending_blocks.last().?.tag == .list_item)
                 p.pending_blocks.items.len - 2
             else
                 null;
@@ -368,7 +368,7 @@ const BlockStart = struct {
 };
 
 fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
-    if (p.pending_blocks.getLast()) |last_pending_block| {
+    if (p.pending_blocks.last()) |last_pending_block| {
         // Close the last block if it is a list and the new block is not a list item
         // or not of the same marker type.
         const should_close_list = last_pending_block.tag == .list and
@@ -383,7 +383,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
         }
     }
 
-    if (p.pending_blocks.getLast()) |last_pending_block| {
+    if (p.pending_blocks.last()) |last_pending_block| {
         // If the last block is a list or list item, check for tightness based
         // on the last line.
         const maybe_containing_list = switch (last_pending_block.tag) {
@@ -401,7 +401,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
     // Start a new list if the new block is a list item and there is no
     // containing list yet.
     if (block_start.tag == .list_item and
-        (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .list))
+        (p.pending_blocks.items.len == 0 or p.pending_blocks.last().?.tag != .list))
     {
         try p.pending_blocks.append(p.allocator, .{
             .tag = .list,
@@ -417,7 +417,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
 
     if (block_start.tag == .table_row) {
         // Likewise, table rows start a table implicitly.
-        if (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .table) {
+        if (p.pending_blocks.items.len == 0 or p.pending_blocks.last().?.tag != .table) {
             try p.pending_blocks.append(p.allocator, .{
                 .tag = .table,
                 .data = .{ .table = .{
@@ -429,7 +429,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
             });
         }
 
-        const current_row = p.scratch_extra.items.len - p.pending_blocks.getLast().?.extra_start;
+        const current_row = p.scratch_extra.items.len - p.pending_blocks.last().?.extra_start;
         if (current_row <= 1) {
             var buffer: [max_table_columns]Node.TableCellAlignment = undefined;
             const table_row = &block_start.data.table_row;
@@ -441,7 +441,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
                     // We need to go back and mark the header row and its column
                     // alignments.
                     const datas = p.nodes.items(.data);
-                    const header_data = datas[p.scratch_extra.getLast().?];
+                    const header_data = datas[p.scratch_extra.last().?];
                     for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| {
                         const alignment = if (i < alignments.len) alignments[i] else .unset;
                         const cell_data = &datas[@backingInt(header_cell)].table_cell;
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
index edece7882eaa79caf502cd493833e902b064856d..23a9573a3fa4a05aadd61516ea0f45eeb2212903 100644
--- a/lib/std/array_list.zig
+++ b/lib/std/array_list.zig
@@ -544,14 +544,22 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
             return self.allocatedSlice()[self.items.len..];
         }
 
-        /// Deprecated in favor of `getLast`
-        pub const getLastOrNull = getLast;
+        /// Deprecated in favor of `last`
+        pub const getLastOrNull = last;
 
-        /// Returns the last element from the list, or `null` if the list is empty.
-        pub fn getLast(self: Self) ?T {
+        /// Returns the last element from the list, or `null` if the list is
+        /// empty.
+        pub fn last(self: Self) ?T {
             if (self.items.len == 0) return null;
             return self.items[self.items.len - 1];
         }
+
+        /// Returns a pointer to the last element from the list, or `null` if
+        /// the list is empty.
+        pub fn lastPtr(self: Self) ?*T {
+            if (self.items.len == 0) return null;
+            return &self.items[self.items.len - 1];
+        }
     };
 }
 
@@ -1391,15 +1399,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
             return self.allocatedSlice()[self.items.len..];
         }
 
-        /// Deprecated in favor of `last`.
-        pub fn getLast(self: Self) ?T {
+        /// Returns the last element from the list, or `null` if the list is
+        /// empty.
+        pub fn last(self: Self) ?T {
             if (self.items.len == 0) return null;
             return self.items[self.items.len - 1];
         }
 
         /// Returns a pointer to the last element from the list, or `null` if
         /// the list is empty.
-        pub fn last(self: Self) ?*T {
+        pub fn lastPtr(self: Self) ?*T {
             if (self.items.len == 0) return null;
             return &self.items[self.items.len - 1];
         }
@@ -2398,7 +2407,7 @@ test "last" {
     try testing.expectEqual(list.last(), null);
 
     try list.append(a, 2);
-    try testing.expectEqual(list.last().?.*, 2);
+    try testing.expectEqual(list.last().?, 2);
 }
 
 test "return OutOfMemory when capacity would exceed maximum usize integer value" {
diff --git a/lib/std/deque.zig b/lib/std/deque.zig
index c21e1b86567f9f84b9e7078fb751f178b193e5e9..ec40c9d1dbc9eb4b20a3025d22508a90d0a2acec 100644
--- a/lib/std/deque.zig
+++ b/lib/std/deque.zig
@@ -696,7 +696,7 @@ fn fuzzAgainstArrayList(_: void, smith: *std.testing.Smith) anyerror!void {
                 try q.ensureTotalCapacityPrecise(q_gpa, q.len + growth);
             },
         }
-        try testing.expectEqual(l.getLast(), q.back());
+        try testing.expectEqual(l.last(), q.back());
         try testing.expectEqual(
             if (l.items.len > 0) l.items[0] else null,
             q.front(),
diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig
index ddbaea460f5f37dd9885bf00db51c1d62d827ff2..605f3752a78e8908539d294300f3f0a1047b2315 100644
--- a/lib/std/zig/Ast/Render.zig
+++ b/lib/std/zig/Ast/Render.zig
@@ -3459,7 +3459,7 @@ const AutoIndentingStream = struct {
     /// Sets current indentation level to be the same as that of the last pushSpace.
     pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void {
         if (ais.space_stack.items.len == 0) return;
-        const curr = ais.space_stack.getLast().?;
+        const curr = ais.space_stack.last().?;
         if (curr.space != space) return;
         ais.space_mode = curr.indent_count;
     }
@@ -3470,7 +3470,7 @@ const AutoIndentingStream = struct {
 
     pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize {
         if (ais.space_stack.items.len == 0) return 0;
-        return ais.space_stack.getLast().?.indent_count * ais.indent_delta;
+        return ais.space_stack.last().?.indent_count * ais.indent_delta;
     }
 
     /// Push default indentation
diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig
index cddeecbe633eb049abbf014caf49ee38fcfe0ce6..6b8afafd0892561e449f5bd6e40ca46d06d16cce 100644
--- a/lib/std/zig/WindowsSdk.zig
+++ b/lib/std/zig/WindowsSdk.zig
@@ -891,7 +891,7 @@ const MsvcLibDir = struct {
 
         lib_dir_buf.appendSliceAssumeCapacity(installation_path);
 
-        if (!Dir.path.isSep(lib_dir_buf.getLast().?)) {
+        if (!Dir.path.isSep(lib_dir_buf.last().?)) {
             try lib_dir_buf.append('\\');
         }
         const installation_path_with_trailing_sep_len = lib_dir_buf.items.len;
@@ -1064,7 +1064,7 @@ const MsvcLibDir = struct {
             errdefer msvc_dir.deinit();
 
             // String might contain trailing slash, so trim it here
-            if (msvc_dir.items.len > "C:\\".len and msvc_dir.getLast().? == '\\') _ = msvc_dir.pop();
+            if (msvc_dir.items.len > "C:\\".len and msvc_dir.last().? == '\\') _ = msvc_dir.pop();
 
             // Remove `\include` at the end of path
             if (std.mem.endsWith(u8, msvc_dir.items, "\\include")) {
@@ -1108,7 +1108,7 @@ const MsvcLibDir = struct {
 
                     try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools
                     // String might contain trailing slash, so trim it here
-                    if (list.items.len > "C:\\".len and list.getLast().? == '\\') _ = list.pop();
+                    if (list.items.len > "C:\\".len and list.last().? == '\\') _ = list.pop();
                     list.shrinkRetainingCapacity(list.items.len - "\\Common7\\Tools".len); // C:\Program Files (x86)\Microsoft Visual Studio 14.0
                     break :base_path list;
                 }
@@ -1131,7 +1131,7 @@ const MsvcLibDir = struct {
                 errdefer path.deinit();
 
                 // String might contain trailing slash, so trim it here
-                if (path.items.len > "C:\\".len and path.getLast().? == '\\') _ = path.pop();
+                if (path.items.len > "C:\\".len and path.last().? == '\\') _ = path.pop();
                 break :base_path path;
             }
             return error.PathNotFound;
diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig
index 890ead68aa27a8c0f7f6cd75b97c822f1e8e77c0..8376a569c45ac7191272eabbd0cb84b73b1843db 100644
--- a/lib/std/zig/llvm/Builder.zig
+++ b/lib/std/zig/llvm/Builder.zig
@@ -2962,7 +2962,7 @@ pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString {
 }
 
 pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString {
-    const start = self.strtab_string_indices.getLast().?;
+    const start = self.strtab_string_indices.last().?;
     const bytes: []const u8 = self.strtab_string_bytes.items[start..];
     const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });
     if (gop.found_existing) {
@@ -9765,7 +9765,7 @@ pub fn deinit(self: *Builder) void {
 
 pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void {
     self.module_asm = aw.toArrayList();
-    if (self.module_asm.getLast()) |last| if (last != '\n')
+    if (self.module_asm.last()) |last| if (last != '\n')
         try self.module_asm.append(self.gpa, '\n');
 }
 
@@ -9811,7 +9811,7 @@ pub fn trailingString(self: *Builder) Allocator.Error!String {
 }
 
 pub fn trailingStringAssumeCapacity(self: *Builder) String {
-    const start = self.string_indices.getLast().?;
+    const start = self.string_indices.last().?;
     const bytes: []const u8 = self.string_bytes.items[start..];
     const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
     if (gop.found_existing) {
@@ -13042,7 +13042,7 @@ pub fn trailingMetadataString(self: *Builder) Allocator.Error!Metadata.String {
 }
 
 pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {
-    const start = self.metadata_string_indices.getLast().?;
+    const start = self.metadata_string_indices.last().?;
     const bytes: []const u8 = self.metadata_string_bytes.items[start..];
     assert(bytes.len > 0);
     const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self });
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 05c329f5d7a1b55b3c0f333ee0985695be364333..2f73d371ea2ed35e82d6923c917581e89ae708c1 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -618,7 +618,7 @@ pub const Object = struct {
             b.module_asm.appendSliceAssumeCapacity(assembly);
             b.module_asm.appendAssumeCapacity('\n');
         }
-        if (b.module_asm.getLast()) |last| {
+        if (b.module_asm.last()) |last| {
             if (last != '\n') try b.module_asm.append(gpa, '\n');
         }
     }
diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig
index 7833c787e039be9d0002886293000ed5424203f6..1b46cfbbc1fcb105d85bdb6a0bf7b05a480cbcea 100644
--- a/src/codegen/spirv/CodeGen.zig
+++ b/src/codegen/spirv/CodeGen.zig
@@ -7280,7 +7280,7 @@ fn structuredBreak(cg: *CodeGen, target_block: Id) !void {
     if (cg.block_terminated) return;
 
     const gpa = cg.gpa;
-    const sblock = cg.block_stack.getLast().?;
+    const sblock = cg.block_stack.last().?;
     const merge_block = switch (sblock.*) {
         .selection => |*merge| blk: {
             const merge_label = cg.allocId();
@@ -7447,7 +7447,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index)
         .operand_2 = this_block,
     });
 
-    const sblock = cg.block_stack.getLast().?;
+    const sblock = cg.block_stack.last().?;
 
     if (ty.isNoReturn(zcu)) {
         // If this block is noreturn, this instruction is the last of a block,
diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig
index 095de8590a768c68a010bb375f07cf0206c83a10..9a087ca03e284f1bf751c52f77ef393a1c1c5896 100644
--- a/src/codegen/x86_64/CodeGen.zig
+++ b/src/codegen/x86_64/CodeGen.zig
@@ -2152,7 +2152,7 @@ fn gen(
 
         const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
             var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
-            while (self.epilogue_relocs.getLast() == last_inst) {
+            while (self.epilogue_relocs.last() == last_inst) {
                 self.epilogue_relocs.items.len -= 1;
                 self.mir_instructions.set(last_inst, .{
                     .tag = .pseudo,
@@ -176978,7 +176978,7 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
     defer block_data.value.deinit(self.gpa);
     if (block_data.value.relocs.items.len > 0) {
         var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
-        while (block_data.value.relocs.getLast() == last_inst) {
+        while (block_data.value.relocs.last() == last_inst) {
             block_data.value.relocs.items.len -= 1;
             self.mir_instructions.set(last_inst, .{
                 .tag = .pseudo,
diff --git a/tools/bsp.zig b/tools/bsp.zig
index bab0bc2c70afb95e99eb51ccf29be357ce4a678f..b86e30c3af07b53b352602e5b480c0d785055830 100644
--- a/tools/bsp.zig
+++ b/tools/bsp.zig
@@ -21,7 +21,7 @@ pub fn main(init: std.process.Init) !void {
     }
     if (maker_args.items.len < 1) try maker_args.append(arena, "zig");
     if (maker_args.items.len < 2) try maker_args.append(arena, "build");
-    if (!std.mem.eql(u8, maker_args.last().?.*, "--listen=-")) try maker_args.append(arena, "--listen=-");
+    if (!std.mem.eql(u8, maker_args.last().?, "--listen=-")) try maker_args.append(arena, "--listen=-");
 
     log.debug("cmd: {f}", .{std.zig.SubprocessCommand{
         .argv = maker_args.items,
-- 
2.54.0


From 17e07ffc6381a1650b6bac5948b9f22d24411982 Mon Sep 17 00:00:00 2001
From: Matthew Lugg 
Date: Thu, 6 Aug 2026 08:07:53 +0100
Subject: [PATCH 173/215] llvm: represent bool as i8 in memory

Follow-up to https://codeberg.org/ziglang/zig/pulls/35711
---
 src/codegen/llvm.zig         | 13 +++++++++----
 src/codegen/llvm/FuncGen.zig | 17 +++++++++++------
 test/llvm_ir.zig             | 20 ++++++++++++++++++++
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 2f73d371ea2ed35e82d6923c917581e89ae708c1..255b2f6bb38d215ce826b67ca2d6b71d38c45de5 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2912,7 +2912,7 @@ pub const Object = struct {
 
         return switch (t.toIntern()) {
             .u0_type => unreachable, // no runtime bits
-            .u1_type => try o.intType(1, repr),
+            .u1_type, .bool_type => try o.intType(1, repr),
             .u8_type, .i8_type => try o.intType(8, repr),
             .u16_type, .i16_type => try o.intType(16, repr),
             .u29_type => try o.intType(29, repr),
@@ -2983,7 +2983,6 @@ pub const Object = struct {
                 // @foo = external global i8
                 return .i8;
             },
-            .bool_type => .i1,
             .anyerror_type => try o.errorIntType(repr),
             .void_type => unreachable, // no runtime bits
             .type_type => unreachable, // no runtime bits
@@ -3472,8 +3471,14 @@ pub const Object = struct {
                 .null => unreachable, // non-runtime value
                 .@"unreachable" => unreachable, // non-runtime value
 
-                .false => .false,
-                .true => .true,
+                .false => switch (repr) {
+                    .as_value => .false,
+                    .in_memory, .memory_access => try o.builder.intConst(.i8, 0),
+                },
+                .true => switch (repr) {
+                    .as_value => .true,
+                    .in_memory, .memory_access => try o.builder.intConst(.i8, 1),
+                },
             },
             .enum_literal => unreachable, // non-runtime value
             .@"extern" => unreachable, // non-runtime value
diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig
index 676fad2f1036445d01e1774b223e1af849d01f82..14e31fd1c09f846fcef7417b46b7681423880cfd 100644
--- a/src/codegen/llvm/FuncGen.zig
+++ b/src/codegen/llvm/FuncGen.zig
@@ -2950,12 +2950,11 @@ fn airIsErr(
         if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
 
     if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
-        const val: Builder.Constant = switch (cond) {
+        return switch (cond) {
             .eq => .true, // 0 == 0
             .ne => .false, // 0 != 0
             else => unreachable,
         };
-        return val.toValue();
     }
 
     if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
@@ -6666,7 +6665,10 @@ fn load(
     const llvm_value_ty = try o.lowerType(load_ty, .as_value);
 
     if (llvm_access_ty != llvm_value_ty) {
-        assert(load_ty.isAbiInt(zcu));
+        const signedness: std.lang.Signedness = switch (load_ty.toIntern()) {
+            .bool_type => .unsigned,
+            else => load_ty.intInfo(zcu).signedness,
+        };
         // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special
         // handling for these, as LLVM's documented semantics are a valid implementation of Zig's
         // semantics. However:
@@ -6685,7 +6687,7 @@ fn load(
         // implemented, but until then, do a normal trunc for packed types.
         return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) {
             .@"struct", .@"union" => .trunc,
-            else => switch (load_ty.intInfo(zcu).signedness) {
+            else => switch (signedness) {
                 .unsigned => .@"trunc nuw",
                 .signed => .@"trunc nsw",
             },
@@ -6740,10 +6742,13 @@ fn store(
     const llvm_value_ty = try o.lowerType(elem_ty, .as_value);
 
     if (llvm_access_ty != llvm_value_ty) {
-        assert(elem_ty.isAbiInt(zcu));
+        const signedness: std.lang.Signedness = switch (elem_ty.toIntern()) {
+            .bool_type => .unsigned,
+            else => elem_ty.intInfo(zcu).signedness,
+        };
         // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see
         // the corresponding comment in `FuncGen.load` for more details.
-        const extended = try fg.wip.cast(switch (elem_ty.intInfo(zcu).signedness) {
+        const extended = try fg.wip.cast(switch (signedness) {
             .unsigned => .zext,
             .signed => .sext,
         }, elem, llvm_access_ty, "");
diff --git a/test/llvm_ir.zig b/test/llvm_ir.zig
index 32221d82878f48be7159a28404dfe3719650c6d9..7949ddab0d19abb763440cdca0d5112cef974da9 100644
--- a/test/llvm_ir.zig
+++ b/test/llvm_ir.zig
@@ -116,6 +116,26 @@ pub fn addCases(cases: *tests.LlvmIrContext) void {
         "null_pointer_is_valid",
         "store i16 42, ptr",
     }, .{});
+
+    cases.addMatches("load and store bool",
+        \\export fn foo(a: *bool, b: *align(2) bool) void {
+        \\    const tmp = a.*;
+        \\    a.* = b.*;
+        \\    b.* = tmp;
+        \\}
+    , &.{
+        // TODO: this should all be one multiline string literal, but `-femit-llvm-ir` is currently
+        // emitting CRLF on Windows, which is a pain to handle here. In future that option will emit
+        // unoptimized LLVM IR emitted directly from Zig, so that bug will go away.
+        "  %3 = load i8, ptr %0, align 1",
+        "  %4 = trunc nuw i8 %3 to i1",
+        "  %5 = load i8, ptr %1, align 2",
+        "  %6 = trunc nuw i8 %5 to i1",
+        "  %7 = zext i1 %6 to i8",
+        "  store i8 %7, ptr %0, align 1",
+        "  %8 = zext i1 %4 to i8",
+        "  store i8 %8, ptr %1, align 2",
+    }, .{ .strip = true });
 }
 
 const std = @import("std");
-- 
2.54.0


From b9852d23089a524dafaa2487f207457b2a183af1 Mon Sep 17 00:00:00 2001
From: Ryan Mehri 
Date: Tue, 4 Aug 2026 11:43:46 -0400
Subject: [PATCH 174/215] Legalize: fix packed struct with OPV and multiple
 other fields

In legalization for packed struct init with an OPV field, we first try
to see if any field accounts for the entire bit size of the struct and
otherwise fall back to a sequence of bitcasts and shifts on each field
(added in fc1c83a363d). However, OPV fields are not accounted for
in the fallback case, which means that codegen eventually panics when
seeing the bit size of 0.

This change makes it so that we ignore all OPV fields in
`packedAggregateInitBlockPayload` since they have no runtime bits.
---
 src/Air/Legalize.zig      |  9 ++++++++-
 test/behavior/bitcast.zig | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/Air/Legalize.zig b/src/Air/Legalize.zig
index 535d9394654a130ef856342f3390473d6664cf93..64fd462b7bd8e041a65c3ec89616db830776349b 100644
--- a/src/Air/Legalize.zig
+++ b/src/Air/Legalize.zig
@@ -2906,12 +2906,18 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
     const orig_ty_pl = l.air_instructions.items(.data)[@backingInt(orig_inst)].ty_pl;
     const agg_ty = orig_ty_pl.ty.toType();
     const agg_field_count = agg_ty.structFieldCount(zcu);
+    var opv_field_count: u32 = 0;
+    for (0..agg_field_count) |field_idx| {
+        const field_ty = agg_ty.fieldType(field_idx, zcu);
+        const field_bits: u16 = @intCast(field_ty.bitSize(zcu));
+        if (field_bits == 0) opv_field_count += 1;
+    }
 
     var bfa_buf: [4 * 32 + 2]Air.Inst.Index = undefined;
     var bfa_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);
     const bfa = bfa_state.allocator();
 
-    const inst_buf = try bfa.alloc(Air.Inst.Index, 4 * agg_field_count + 2);
+    const inst_buf = try bfa.alloc(Air.Inst.Index, 4 * (agg_field_count - opv_field_count) + 2);
     defer bfa.free(inst_buf);
 
     var main_block: Block = .init(inst_buf);
@@ -2927,6 +2933,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro
         field_idx -= 1;
         const field_ty = agg_ty.fieldType(field_idx, zcu);
         const field_bits: u16 = @intCast(field_ty.bitSize(zcu));
+        if (field_bits == 0) continue;
         assert(field_bits < num_bits);
         const field_uint_ty = try pt.intType(.unsigned, field_bits);
         const field_bit_size_ref: Air.Inst.Ref = .fromValue(try pt.intValue(shift_ty, field_bits));
diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig
index 785daa0d3194b00d43c00760a11199075d9377dd..d790d68416add0ba62603eaabaa691d1bdfe9c32 100644
--- a/test/behavior/bitcast.zig
+++ b/test/behavior/bitcast.zig
@@ -432,6 +432,22 @@ test "@bitCast of packed struct with void field to integer" {
     try comptime S.doTheTest(123);
 }
 
+test "@bitCast of packed struct with void field and multiple integers" {
+    const S = packed struct {
+        x: u8,
+        v: void,
+        y: u8,
+
+        fn doTheTest(x: u8, y: u8) !void {
+            const foo = @as(@This(), .{ .x = x, .v = {}, .y = y });
+            const as_int: u16 = @bitCast(foo);
+            try expect(as_int == @as(u16, y) << 8 | x);
+        }
+    };
+    try S.doTheTest(123, 45);
+    try comptime S.doTheTest(123, 45);
+}
+
 test "@bitCast vector to array with different element size" {
     if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 
-- 
2.54.0


From 340e53a65e8175b6d98b11ec2f33461395f722d1 Mon Sep 17 00:00:00 2001
From: ilovapples 
Date: Thu, 6 Aug 2026 17:58:56 -0500
Subject: [PATCH 175/215] compiler_rt: downgrade ARMv6 Thumb instructions to
 ARMv4-valid variants

---
 lib/compiler_rt/int_from_float.zig | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig
index 8eb4c2fcbc79f9d254255372062e473443bffdde..20d87eb3f9b927b41a5e59aea8602405ffdb0b58 100644
--- a/lib/compiler_rt/int_from_float.zig
+++ b/lib/compiler_rt/int_from_float.zig
@@ -119,7 +119,7 @@ fn __aeabi_fixsfti(_: compiler_rt.f32.Abi) callconv(.naked) i128 {
     switch (builtin.abi.float()) {
         .soft => asm volatile (
             \\ push {r0-r4, lr}
-            \\ mov r1, r0
+            \\ movs r1, r0
             \\ mov r0, sp
             \\ bl %[__fixsfti]
             \\ pop {r0-r4, pc}
@@ -175,8 +175,8 @@ fn __aeabi_fixdfti(_: compiler_rt.f64.Abi) callconv(.naked) i128 {
     switch (builtin.abi.float()) {
         .soft => asm volatile (
             \\ push {r0-r4, lr}
-            \\ mov r3, r1
-            \\ mov r2, r0
+            \\ movs r3, r1
+            \\ movs r2, r0
             \\ mov r0, sp
             \\ bl %[__fixdfti]
             \\ pop {r0-r4, pc}
@@ -382,7 +382,7 @@ fn __aeabi_fixunssfti(_: compiler_rt.f32.Abi) callconv(.naked) u128 {
     switch (builtin.abi.float()) {
         .soft => asm volatile (
             \\ push {r0-r4, lr}
-            \\ mov r1, r0
+            \\ movs r1, r0
             \\ mov r0, sp
             \\ bl %[__fixunssfti]
             \\ pop {r0-r4, pc}
@@ -438,8 +438,8 @@ fn __aeabi_fixunsdfti(_: compiler_rt.f64.Abi) callconv(.naked) u128 {
     switch (builtin.abi.float()) {
         .soft => asm volatile (
             \\ push {r0-r4, lr}
-            \\ mov r3, r1
-            \\ mov r2, r0
+            \\ movs r3, r1
+            \\ movs r2, r0
             \\ mov r0, sp
             \\ bl %[__fixunsdfti]
             \\ pop {r0-r4, pc}
-- 
2.54.0


From 7b720ad26b589764078330aa924bde79c627c8f8 Mon Sep 17 00:00:00 2001
From: drex_vk 
Date: Fri, 7 Aug 2026 15:49:15 +0200
Subject: [PATCH 176/215] bootstrap.c: fix __WIN32__ macro -> _WIN32

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35963
---
 bootstrap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/bootstrap.c b/bootstrap.c
index 50297f34fdc429cdc75f1f338c4a9cd7d5aea5ab..e75e1c42ef0c8d59df5afb827d173ac755f60e18 100644
--- a/bootstrap.c
+++ b/bootstrap.c
@@ -56,7 +56,7 @@ static void panic(const char *reason) {
     #define GCC_BUG_119085_PRESENT 0
 #endif
 
-#if defined(__WIN32__)
+#if defined(_WIN32)
 #error TODO write the functionality for executing child process into this build script
 #else
 
@@ -99,7 +99,7 @@ static void print_and_run(const char **argv) {
 static const char *get_host_os(void) {
     const char *host_os = getenv("ZIG_HOST_TARGET_OS");
     if (host_os != NULL) return host_os;
-#if defined(__WIN32__)
+#if defined(_WIN32)
     return "windows";
 #elif defined(__APPLE__)
     return "macos";
-- 
2.54.0


From 1ebc455715958d131cc00caa9aa6c58fa8e7b726 Mon Sep 17 00:00:00 2001
From: Noam Rothschild 
Date: Sat, 2 May 2026 20:38:13 +0300
Subject: [PATCH 177/215] std: fixed a doc comment on IoUring.copy_cqes
 (#35175)

---
 lib/std/os/linux/IoUring.zig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig
index 49720ac4eaf641b39fdd0f1ea066ddc4245857ba..a3723244cd9b23a04bd2dacf800fd83b95d39a4c 100644
--- a/lib/std/os/linux/IoUring.zig
+++ b/lib/std/os/linux/IoUring.zig
@@ -267,7 +267,7 @@ pub fn cq_ready(self: *IoUring) u32 {
 }
 
 /// Copies as many CQEs as are ready, and that can fit into the destination `cqes` slice.
-/// If none are available, enters into the kernel to wait for at most `wait_nr` CQEs.
+/// If none are available, enters into the kernel to wait for at least `wait_nr` CQEs.
 /// Returns the number of CQEs copied, advancing the CQ ring.
 /// Provides all the wait/peek methods found in liburing, but with batching and a single method.
 /// The rationale for copying CQEs rather than copying pointers is that pointers are 8 bytes
-- 
2.54.0


From fafbc70ac58e056373eed8f2f21ff348f1e3a78a Mon Sep 17 00:00:00 2001
From: Corentin Kerisit 
Date: Fri, 7 Aug 2026 16:14:05 +0200
Subject: [PATCH 178/215] std.debug.MachOFile: support loading DWARF from
 adjacent dSYM (#35582)

Fixes #31797

I finally had time to work on this.

I've implemented it so that, when an adjacent dSYM exist and its uuid match that of the current binary, we load its DWARF and use that for all getDwarfForAddress requests.
All of this is done eagerly at `MachOFile.load` for simplicity rather than later and lazier. Happy to change that to whatever you think is best.

This implementation is quite minimal and makes dSYM support "best-effort" as in, it treats dSYM parsing error as non-fatal and fallbacks using the current stabs/ofiles mechanism.

You can test it that way on macOS:

```
zig build-exe panic.zig
dsymutil panic -o panic.dSYM
strip -S panic
./panic
```

with panic.zig:
```
pub fn main() void {
    @panic("panic");
}
```

Before:
```
thread 57569166 panic: panic
???:?:?: 0x103071c2b in _panic.main (/private/tmp/panic)
???:?:?: 0x103071bb3 in _main (/private/tmp/panic)
???:?:?: 0x180d5ab97 in start (/usr/lib/dyld)
fish: Job 1, './panic' terminated by signal SIGABRT (Abort)
```

After:
```
thread 57569653 panic: panic
/private/tmp/panic.zig:2:5: 0x1029d771b in main (panic)
    @panic("panic");
    ^
/Users/cerisier/code/codeberg.org/ziglang/zig/lib/std/start.zig:698:59: 0x1029d76a3 in callMain (panic)
    if (fn_info.params.len == 0) return wrapMain(root.main());
                                                          ^
???:?:?: 0x180d5ab97 in start (/usr/lib/dyld)
fish: Job 1, './panic' terminated by signal SIGABRT (Abort)
```

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35582
Reviewed-by: mlugg 
---
 lib/std/debug/MachOFile.zig | 221 +++++++++++++++++++++++++++---------
 1 file changed, 169 insertions(+), 52 deletions(-)

diff --git a/lib/std/debug/MachOFile.zig b/lib/std/debug/MachOFile.zig
index 8b35d7541d05caae74e065d6146ebbffd4e8d3e4..220876105ec527ba88a3e3b8fb02353741ff3055 100644
--- a/lib/std/debug/MachOFile.zig
+++ b/lib/std/debug/MachOFile.zig
@@ -2,6 +2,8 @@ mapped_memory: []align(std.heap.page_size_min) const u8,
 symbols: []const Symbol,
 strings: []const u8,
 text_vmaddr: u64,
+uuid: ?Uuid,
+adjacent_dsym: ?DsymFile,
 
 /// Key is index into `strings` of the file path.
 ofiles: std.array_hash_map.Auto(u32, Error!OFile),
@@ -16,6 +18,7 @@ pub const Error = error{
 };
 
 pub fn deinit(mf: *MachOFile, gpa: Allocator) void {
+    if (mf.adjacent_dsym) |*dsym| dsym.deinit(gpa);
     for (mf.ofiles.values()) |*maybe_of| {
         const of = &(maybe_of.* catch continue);
         posix.munmap(of.mapped_memory);
@@ -36,48 +39,7 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
     const all_mapped_memory = try mapDebugInfoFile(io, path);
     errdefer posix.munmap(all_mapped_memory);
 
-    // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal
-    // binary": a simple file format which contains Mach-O binaries for multiple targets. For
-    // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images
-    // for both ARM64 macOS and x86_64 macOS.
-    if (all_mapped_memory.len < 4) return error.InvalidMachO;
-    const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little);
-
-    // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`.
-    const mapped_macho = switch (magic) {
-        macho.MH_MAGIC_64 => all_mapped_memory,
-
-        macho.FAT_CIGAM => mapped_macho: {
-            // This is the universal binary format (aka a "fat binary").
-            var fat_r: Io.Reader = .fixed(all_mapped_memory);
-            const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) {
-                error.ReadFailed => unreachable,
-                error.EndOfStream => return error.InvalidMachO,
-            };
-            const want_cpu_type = switch (arch) {
-                .x86_64 => macho.CPU_TYPE_X86_64,
-                .aarch64 => macho.CPU_TYPE_ARM64,
-                else => unreachable,
-            };
-            for (0..hdr.nfat_arch) |_| {
-                const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) {
-                    error.ReadFailed => unreachable,
-                    error.EndOfStream => return error.InvalidMachO,
-                };
-                if (fat_arch.cputype != want_cpu_type) continue;
-                if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO;
-                break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size];
-            }
-            // `arch` was not present in the fat binary.
-            return error.MissingDebugInfo;
-        },
-
-        // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It
-        // will be fairly easy to add support here if necessary; it's very similar to above.
-        macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo,
-
-        else => return error.InvalidMachO,
-    };
+    const mapped_macho = try selectMachOSlice(all_mapped_memory, arch);
 
     var r: Io.Reader = .fixed(mapped_macho);
     const hdr = r.takeStruct(macho.mach_header_64, .little) catch |err| switch (err) {
@@ -88,21 +50,26 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
     if (hdr.magic != macho.MH_MAGIC_64)
         return error.InvalidMachO;
 
-    const symtab: macho.symtab_command, const text_vmaddr: u64 = lcs: {
+    const symtab: macho.symtab_command, const text_vmaddr: u64, const uuid: ?Uuid = lcs: {
         var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);
         var symtab: ?macho.symtab_command = null;
         var text_vmaddr: ?u64 = null;
+        var uuid: ?Uuid = null;
         while (try it.next()) |cmd| switch (cmd.hdr.cmd) {
             .SYMTAB => symtab = cmd.cast(macho.symtab_command) orelse return error.InvalidMachO,
             .SEGMENT_64 => if (cmd.cast(macho.segment_command_64)) |seg_cmd| {
                 if (!mem.eql(u8, seg_cmd.segName(), "__TEXT")) continue;
                 text_vmaddr = seg_cmd.vmaddr;
             },
+            .UUID => if (cmd.cast(macho.uuid_command)) |uuid_cmd| {
+                uuid = uuid_cmd.uuid;
+            },
             else => {},
         };
         break :lcs .{
             symtab orelse return error.MissingDebugInfo,
             text_vmaddr orelse return error.MissingDebugInfo,
+            uuid,
         };
     };
 
@@ -253,15 +220,27 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch)
     // This sort is so that we can binary search later.
     mem.sort(Symbol, symbols_slice, {}, Symbol.addressLessThan);
 
+    const adjacent_dsym = if (uuid) |expected_uuid|
+        try loadAdjacentDsym(gpa, io, path, arch, expected_uuid)
+    else
+        null;
+
     return .{
         .mapped_memory = all_mapped_memory,
         .symbols = symbols_slice,
         .strings = strings,
         .ofiles = .empty,
         .text_vmaddr = text_vmaddr,
+        .uuid = uuid,
+        .adjacent_dsym = adjacent_dsym,
     };
 }
+
 pub fn getDwarfForAddress(mf: *MachOFile, gpa: Allocator, io: Io, vaddr: u64) !struct { *Dwarf, u64 } {
+    if (mf.adjacent_dsym) |*dsym| {
+        return .{ &dsym.dwarf, vaddr };
+    }
+
     const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo;
 
     if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo;
@@ -324,6 +303,16 @@ const OFile = struct {
     };
 };
 
+const DsymFile = struct {
+    mapped_memory: []align(std.heap.page_size_min) const u8,
+    dwarf: Dwarf,
+
+    fn deinit(df: *DsymFile, gpa: Allocator) void {
+        df.dwarf.deinit(gpa);
+        posix.munmap(df.mapped_memory);
+    }
+};
+
 const Symbol = struct {
     strx: u32,
     addr: u64,
@@ -394,6 +383,74 @@ fn appendStabSymbol(
     }
 }
 
+fn loadAdjacentDsym(
+    gpa: Allocator,
+    io: Io,
+    binary_path: []const u8,
+    arch: std.Target.Cpu.Arch,
+    uuid: Uuid,
+) Error!?DsymFile {
+    const s = std.fs.path.sep_str;
+    const dsym_path = try std.fmt.allocPrint(
+        gpa,
+        "{s}.dSYM" ++ s ++ "Contents" ++ s ++ "Resources" ++ s ++ "DWARF" ++ s ++ "{s}",
+        .{ binary_path, std.fs.path.basename(binary_path) },
+    );
+    defer gpa.free(dsym_path);
+    return loadDsymFile(gpa, io, dsym_path, arch, uuid) catch |err| switch (err) {
+        error.MissingDebugInfo,
+        error.InvalidMachO,
+        error.InvalidDwarf,
+        error.UnsupportedDebugInfo,
+        error.ReadFailed,
+        => null,
+        error.OutOfMemory => |e| return e,
+    };
+}
+
+fn loadDsymFile(
+    gpa: Allocator,
+    io: Io,
+    path: []const u8,
+    arch: std.Target.Cpu.Arch,
+    expected_uuid: Uuid,
+) Error!DsymFile {
+    const all_mapped_memory = try mapDebugInfoFile(io, path);
+    errdefer posix.munmap(all_mapped_memory);
+    const mapped_macho = try selectMachOSlice(all_mapped_memory, arch);
+
+    var r: Io.Reader = .fixed(mapped_macho);
+    const hdr = r.takeStruct(macho.mach_header_64, .little) catch |err| switch (err) {
+        error.ReadFailed => unreachable,
+        error.EndOfStream => return error.InvalidMachO,
+    };
+    if (hdr.magic != macho.MH_MAGIC_64) return error.InvalidMachO;
+    if (hdr.filetype != macho.MH_DSYM) return error.MissingDebugInfo;
+
+    var uuid: ?Uuid = null;
+    var dwarf_sections: ?[]align(1) const macho.section_64 = null;
+
+    var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]);
+    while (try it.next()) |lc| switch (lc.hdr.cmd) {
+        .SEGMENT_64 => if (lc.cast(macho.segment_command_64)) |seg_cmd| {
+            if (!mem.eql(u8, "__DWARF", seg_cmd.segName())) continue;
+            dwarf_sections = lc.getSections();
+        },
+        .UUID => if (lc.cast(macho.uuid_command)) |uuid_cmd| {
+            uuid = uuid_cmd.uuid;
+        },
+        else => {},
+    };
+
+    const actual_uuid = uuid orelse return error.MissingDebugInfo;
+    if (!mem.eql(u8, &actual_uuid, &expected_uuid)) return error.MissingDebugInfo;
+
+    return .{
+        .mapped_memory = all_mapped_memory,
+        .dwarf = try loadDwarfFromSections(gpa, mapped_macho, dwarf_sections orelse return error.MissingDebugInfo),
+    };
+}
+
 fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
     const all_mapped_memory, const mapped_ofile = map: {
         const open_paren = paren: {
@@ -497,8 +554,24 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
         gop.key_ptr.* = @intCast(sym_index);
     }
 
+    const dwarf = try loadDwarfFromSections(gpa, mapped_ofile, seg_cmd.getSections());
+
+    return .{
+        .mapped_memory = all_mapped_memory,
+        .dwarf = dwarf,
+        .strtab = strtab,
+        .symtab_raw = symtab_raw,
+        .symbols_by_name = symbols_by_name.move(),
+    };
+}
+
+fn loadDwarfFromSections(
+    gpa: Allocator,
+    mapped_macho: []const u8,
+    section_headers: []align(1) const macho.section_64,
+) !Dwarf {
     var sections: Dwarf.SectionArray = @splat(null);
-    for (seg_cmd.getSections()) |sect_raw| {
+    for (section_headers) |sect_raw| {
         var sect = sect_raw;
         if (builtin.cpu.arch.endian() != .little) std.mem.byteSwapAllFields(macho.section_64, §);
 
@@ -511,8 +584,8 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
             if (mem.eql(u8, section_name_trunc, sect.sectName())) break i;
         } else continue;
 
-        if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO;
-        const section_bytes = mapped_ofile[sect.offset..][0..sect.size];
+        if (mapped_macho.len < sect.offset + sect.size) return error.InvalidMachO;
+        const section_bytes = mapped_macho[sect.offset..][0..sect.size];
         sections[section_index] = .{
             .data = section_bytes,
             .owned = false,
@@ -542,13 +615,56 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile {
         => |e| return e,
     };
 
-    return .{
-        .mapped_memory = all_mapped_memory,
-        .dwarf = dwarf,
-        .strtab = strtab,
-        .symtab_raw = symtab_raw,
-        .symbols_by_name = symbols_by_name.move(),
+    return dwarf;
+}
+
+fn selectMachOSlice(
+    all_mapped_memory: []align(std.heap.page_size_min) const u8,
+    arch: std.Target.Cpu.Arch,
+) Error![]const u8 {
+    // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal
+    // binary": a simple file format which contains Mach-O binaries for multiple targets. For
+    // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images
+    // for both ARM64 macOS and x86_64 macOS.
+    if (all_mapped_memory.len < 4) return error.InvalidMachO;
+    const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little);
+
+    // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`.
+    const mapped_macho = switch (magic) {
+        macho.MH_MAGIC_64 => all_mapped_memory,
+
+        macho.FAT_CIGAM => mapped_macho: {
+            // This is the universal binary format (aka a "fat binary").
+            var fat_r: Io.Reader = .fixed(all_mapped_memory);
+            const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) {
+                error.ReadFailed => unreachable,
+                error.EndOfStream => return error.InvalidMachO,
+            };
+            const want_cpu_type = switch (arch) {
+                .x86_64 => macho.CPU_TYPE_X86_64,
+                .aarch64 => macho.CPU_TYPE_ARM64,
+                else => unreachable,
+            };
+            for (0..hdr.nfat_arch) |_| {
+                const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) {
+                    error.ReadFailed => unreachable,
+                    error.EndOfStream => return error.InvalidMachO,
+                };
+                if (fat_arch.cputype != want_cpu_type) continue;
+                if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO;
+                break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size];
+            }
+            // `arch` was not present in the fat binary.
+            return error.MissingDebugInfo;
+        },
+
+        // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It
+        // will be fairly easy to add support here if necessary; it's very similar to above.
+        macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo,
+
+        else => return error.InvalidMachO,
     };
+    return mapped_macho;
 }
 
 /// Uses `mmap` to map the file at `path` into memory.
@@ -586,4 +702,5 @@ const testing = std.testing;
 
 const builtin = @import("builtin");
 
+const Uuid = @FieldType(macho.uuid_command, "uuid");
 const MachOFile = @This();
-- 
2.54.0


From d5bd19d471198c0175f2f8875b262b9e13756c25 Mon Sep 17 00:00:00 2001
From: Amilia MacIntyre 
Date: Fri, 24 Jul 2026 14:22:54 -0400
Subject: [PATCH 179/215] std.Io: handle EACCES in calls to `bind`

---
 lib/std/Io/Kqueue.zig   | 1 +
 lib/std/Io/Threaded.zig | 1 +
 lib/std/Io/Uring.zig    | 1 +
 lib/std/Io/net.zig      | 4 ++++
 4 files changed, 7 insertions(+)

diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig
index d34d4132a1a37646303191831a3c050cd579c500..ce339f029f3a9bab3627154658bd53b6af5c14f2 100644
--- a/lib/std/Io/Kqueue.zig
+++ b/lib/std/Io/Kqueue.zig
@@ -1422,6 +1422,7 @@ fn posixBind(
             .INTR => continue,
             .CANCELED => return error.Canceled,
 
+            .ACCES => return error.AccessDenied,
             .ADDRINUSE => return error.AddressInUse,
             .BADF => |err| return errnoBug(err), // File descriptor used after closed.
             .INVAL => |err| return errnoBug(err), // invalid parameters
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index 2c48909a6d169d8ed3ddc5cbc385f176a319864a..8f67e78a75516624e4a5beffc3969a50ced92875 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -12086,6 +12086,7 @@ fn posixBind(
             else => |e| {
                 syscall.finish();
                 switch (e) {
+                    .ACCES => return error.AccessDenied,
                     .ADDRINUSE => return error.AddressInUse,
                     .BADF => |err| return errnoBug(err), // File descriptor used after closed.
                     .INVAL => |err| return errnoBug(err), // invalid parameters
diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig
index 6edf381378148e64941e64559150f77ad94a0650..d59b2d45b461b03eafaa4ae188bb50819b2a9a2d 100644
--- a/lib/std/Io/Uring.zig
+++ b/lib/std/Io/Uring.zig
@@ -5298,6 +5298,7 @@ fn bind(
         switch (cancel_region.errno()) {
             .SUCCESS => return,
             .INTR, .CANCELED => {},
+            .ACCES => return error.AccessDenied,
             .ADDRINUSE => return error.AddressInUse,
             .BADF => |err| return errnoBug(err), // File descriptor used after closed.
             .INVAL => |err| return errnoBug(err), // invalid parameters
diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig
index d7454a9d5db4d704f29fed8147da260562e3e660..9c2e3d3a693c0cd1f5af53ee610c2a64e36ad4b3 100644
--- a/lib/std/Io/net.zig
+++ b/lib/std/Io/net.zig
@@ -198,6 +198,8 @@ pub const IpAddress = union(enum) {
     }
 
     pub const ListenError = error{
+        /// The address is protected and the current user does not have permission to bind it.
+        AccessDenied,
         /// The address is already taken. Can occur when bound port is 0 but
         /// all ephemeral ports are already in use.
         AddressInUse,
@@ -254,6 +256,8 @@ pub const IpAddress = union(enum) {
     }
 
     pub const BindError = error{
+        /// The address is protected and the current user does not have permission to bind it.
+        AccessDenied,
         /// The address is already taken. Can occur when bound port is 0 but
         /// all ephemeral ports are already in use.
         AddressInUse,
-- 
2.54.0


From ce02115365759a9b7f9ccfdd8577bee20da54b84 Mon Sep 17 00:00:00 2001
From: K4 
Date: Sun, 5 Jul 2026 16:20:08 +0300
Subject: [PATCH 180/215] make `lib/std/crypto/benchmark.zig` compile resolves
 https://codeberg.org/ziglang/zig/issues/36054

---
 lib/std/crypto/benchmark.zig      | 4 ++--
 lib/std/crypto/kangarootwelve.zig | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig
index 2cc49344b39108a118c000506b531e7520d91047..014a7d3558e1a2cd0d3131be834261d97416b613 100644
--- a/lib/std/crypto/benchmark.zig
+++ b/lib/std/crypto/benchmark.zig
@@ -454,8 +454,8 @@ fn benchmarkPwhash(
 
     const strHash = ty.strHash;
     const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn";
-    const needs_io = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type == std.Io;
-    const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;
+    const needs_io = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? == std.Io;
+    const needs_salt = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? != std.Io;
     const salt: [16]u8 = @splat(0);
 
     const start = benchTime(io);
diff --git a/lib/std/crypto/kangarootwelve.zig b/lib/std/crypto/kangarootwelve.zig
index 735d476591854adae4ea5a4a417a3ce6d8a67b86..b71d3c093d2fe980eb94781bbdb87705eb5c6f27 100644
--- a/lib/std/crypto/kangarootwelve.zig
+++ b/lib/std/crypto/kangarootwelve.zig
@@ -885,7 +885,7 @@ fn ktMultiThreaded(
 
         var select_outstanding: usize = 0;
         var select: Select = .init(io, select_buf);
-        defer select.cancel();
+        defer select.cancelDiscard();
         var batches_spawned: usize = 0;
         var next_to_process: usize = 0;
 
-- 
2.54.0


From 9d27b6289b592d312618d87819d533dc6e140ccd Mon Sep 17 00:00:00 2001
From: Henry Kupty 
Date: Fri, 7 Aug 2026 16:45:28 +0200
Subject: [PATCH 181/215] std.http: add QUERY method (#35956)

as per [rfc10008](https://datatracker.ietf.org/doc/html/rfc10008), QUERY is a safe, cacheable and idempotent method with body

ref: ziglang/zig#35955

Co-authored-by: Henry Kupty 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35956
---
 lib/std/http.zig | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/lib/std/http.zig b/lib/std/http.zig
index 3a255580576b23e49bcecdfa88503259d458e1f5..c2966cb2558f0c0ebee2f1e2d1bdcf6a78ad8356 100644
--- a/lib/std/http.zig
+++ b/lib/std/http.zig
@@ -20,6 +20,8 @@ pub const Version = enum {
 /// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition
 ///
 /// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH
+///
+/// https://datatracker.ietf.org/doc/html/rfc10008#name-query-method QUERY
 pub const Method = enum {
     GET,
     HEAD,
@@ -30,12 +32,13 @@ pub const Method = enum {
     OPTIONS,
     TRACE,
     PATCH,
+    QUERY,
 
     /// Returns true if a request of this method is allowed to have a body
     /// Actual behavior from servers may vary and should still be checked
     pub fn requestHasBody(m: Method) bool {
         return switch (m) {
-            .POST, .PUT, .PATCH => true,
+            .POST, .PUT, .PATCH, .QUERY => true,
             .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false,
         };
     }
@@ -44,7 +47,7 @@ pub const Method = enum {
     /// Actual behavior from clients may vary and should still be checked
     pub fn responseHasBody(m: Method) bool {
         return switch (m) {
-            .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH => true,
+            .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH, .QUERY => true,
             .HEAD, .TRACE => false,
         };
     }
@@ -56,7 +59,7 @@ pub const Method = enum {
     /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1
     pub fn safe(m: Method) bool {
         return switch (m) {
-            .GET, .HEAD, .OPTIONS, .TRACE => true,
+            .GET, .HEAD, .OPTIONS, .TRACE, .QUERY => true,
             .POST, .PUT, .DELETE, .CONNECT, .PATCH => false,
         };
     }
@@ -70,7 +73,7 @@ pub const Method = enum {
     /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2
     pub fn idempotent(m: Method) bool {
         return switch (m) {
-            .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true,
+            .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE, .QUERY => true,
             .CONNECT, .POST, .PATCH => false,
         };
     }
@@ -83,7 +86,7 @@ pub const Method = enum {
     /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3
     pub fn cacheable(m: Method) bool {
         return switch (m) {
-            .GET, .HEAD => true,
+            .GET, .HEAD, .QUERY => true,
             .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .TRACE, .PATCH => false,
         };
     }
-- 
2.54.0


From c0924842744fea67df49c9942b99d855b83578e5 Mon Sep 17 00:00:00 2001
From: Robbie Lyman 
Date: Fri, 7 Aug 2026 11:54:36 -0400
Subject: [PATCH 182/215] fix(Allocator): test leak

---
 lib/std/mem/Allocator.zig | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index d50c7c1764bfe5b38a78d0761bb4983736839e41..98164b5b21abf095f3c65c9cd0abebe21b00193d 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -627,7 +627,10 @@ test "free single-pointer to array" {
         const allocation = try allocator.alloc(u32, 128);
         allocation[127] = 0;
         const ptr: *[127:0]u32 = allocation[0..127 :0];
-        const new = try allocator.realloc(ptr, 16);
-        allocator.free(new);
+        if (allocator.realloc(ptr, 16)) |new| {
+            allocator.free(new);
+        } else |_| {
+            allocator.free(allocation);
+        }
     }
 }
-- 
2.54.0


From 8bf3941f6ba1df180ed29636f548538e748b157b Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 15:37:58 -0700
Subject: [PATCH 183/215] std.Build: remove dead fields

These were originally intended to tell the configure script whether or
not those third party integrations were enabled.

This is now a problem because we want to produce a configuration file
that is indendent of whether such external integrations will be enabled,
so that the logic does not need to be re-executed when those flags are
changed on the command line.

If we wish to make this feature interact with the configure script, let
us consider carefully how to add it in a future enhancement, and not
leave these dead fields sitting around in the meantime.

closes #35607
---
 lib/std/Build.zig | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index eed57a0b15b47b23b54b412c4305f12020b9773c..0258ce941c5fbb32bb162095d2ebec28262f6fc6 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -45,17 +45,6 @@ debug_log_scopes: []const []const u8 = &.{},
 /// Set to 0 to disable stack collection.
 debug_stack_frames_count: u8 = 8,
 
-/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
-enable_darling: bool = false,
-/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
-enable_qemu: bool = false,
-/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
-enable_rosetta: bool = false,
-/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
-enable_wasmtime: bool = false,
-/// Use system Wine installation to run cross compiled Windows build artifacts.
-enable_wine: bool = false,
-
 dep_prefix: []const u8 = "",
 
 modules: std.array_hash_map.String(*Module),
@@ -388,11 +377,6 @@ fn createChild(
         .default_step = undefined,
         .top_level_steps = .{},
         .debug_log_scopes = parent.debug_log_scopes,
-        .enable_darling = parent.enable_darling,
-        .enable_qemu = parent.enable_qemu,
-        .enable_rosetta = parent.enable_rosetta,
-        .enable_wasmtime = parent.enable_wasmtime,
-        .enable_wine = parent.enable_wine,
         .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
         .modules = .empty,
         .named_writefiles = .empty,
-- 
2.54.0


From 3a8984f254addc3de4423bab367192c77ebba4fc Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 15:45:32 -0700
Subject: [PATCH 184/215] delete standalone test: debug_io_color

This test has a workaround in it (setting has_side_effects=true) which
made it problematic to maintain. Delete the test instead.
---
 lib/std/Build/Step/Run.zig               |  2 +
 test/standalone/build.zig.zon            |  3 -
 test/standalone/debug_io_color/build.zig | 95 ------------------------
 test/standalone/debug_io_color/main.zig  |  7 --
 4 files changed, 2 insertions(+), 105 deletions(-)
 delete mode 100644 test/standalone/debug_io_color/build.zig
 delete mode 100644 test/standalone/debug_io_color/main.zig

diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig
index 9e1f3ca7047585a13fcae9b77de0afb6c45f9eee..564dd2507dca28de63f943054b787c8602cc4f86 100644
--- a/lib/std/Build/Step/Run.zig
+++ b/lib/std/Build/Step/Run.zig
@@ -68,9 +68,11 @@ rename_step_with_output_arg: bool,
 /// executed binary will not fail the build if the binary cannot be executed
 /// due to being for a foreign binary to the host system which is running the
 /// build graph.
+///
 /// Command-line arguments such as -fqemu and -fwasmtime may affect whether a
 /// binary is detected as foreign, as well as system configuration such as
 /// Rosetta (macOS) and binfmt_misc (Linux).
+///
 /// If this Run step is considered to have side-effects, then this flag does
 /// nothing.
 skip_foreign_checks: bool,
diff --git a/test/standalone/build.zig.zon b/test/standalone/build.zig.zon
index 190394704ae48cd28406511353905a2f8675dd63..e134d00bd7d5977cda3341787a3dfefca86b4b7c 100644
--- a/test/standalone/build.zig.zon
+++ b/test/standalone/build.zig.zon
@@ -187,9 +187,6 @@
         .posix = .{
             .path = "posix",
         },
-        .debug_io_color = .{
-            .path = "debug_io_color",
-        },
         .elf2 = .{
             .path = "elf2",
         },
diff --git a/test/standalone/debug_io_color/build.zig b/test/standalone/debug_io_color/build.zig
deleted file mode 100644
index 22ce7c8c22f9ab3299bf14e07e7c0b7a23f367c6..0000000000000000000000000000000000000000
--- a/test/standalone/debug_io_color/build.zig
+++ /dev/null
@@ -1,95 +0,0 @@
-const std = @import("std");
-
-pub fn build(b: *std.Build) void {
-    const test_step = b.step("test", "Test");
-    b.default_step = test_step;
-
-    // Most targets handle color the same way, regardless of whether libc is linked.
-    const native_target = b.graph.host;
-    addTestCases(test_step, native_target, false);
-    addTestCases(test_step, native_target, true);
-
-    // WASI behaves differently depending on whether libc is linked.
-    if (b.enable_wasmtime) {
-        const wasi_target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi });
-        addTestCases(test_step, wasi_target, false);
-        addTestCases(test_step, wasi_target, true);
-    }
-}
-
-fn addTestCases(
-    test_step: *std.Build.Step,
-    target: std.Build.ResolvedTarget,
-    link_libc: bool,
-) void {
-    const b = test_step.owner;
-    const exe = b.addExecutable(.{
-        .name = b.fmt("{s}{s}", .{ @tagName(target.result.os.tag), if (link_libc) "-libc" else "" }),
-        .root_module = b.createModule(.{
-            .root_source_file = b.path("main.zig"),
-            .target = target,
-            .link_libc = link_libc,
-        }),
-    });
-
-    // Should reflect 'std.process.Environ.Block' and 'std.Io.Threaded.init_single_threaded'.
-    const debug_io_can_read_environ = switch (target.result.os.tag) {
-        .windows => true,
-        .wasi, .emscripten => link_libc,
-        .freestanding, .other => false,
-        else => true,
-    };
-
-    // Don't forget to account for whether the build process's stderr supports color.
-    const parent_stderr_color_enabled = (std.Io.Terminal.Mode.detect(b.graph.io, .stderr(), false, false) catch unreachable) != .no_color;
-
-    _ = addTestCase(test_step, exe, "neither", .inherit, .manual, parent_stderr_color_enabled);
-    _ = addTestCase(test_step, exe, "neither", .redirect, .manual, false);
-    _ = addTestCase(test_step, exe, "no_color", .inherit, .disable, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
-    _ = addTestCase(test_step, exe, "no_color", .redirect, .disable, false);
-    _ = addTestCase(test_step, exe, "clicolor_force", .inherit, .enable, if (debug_io_can_read_environ) true else parent_stderr_color_enabled);
-    _ = addTestCase(test_step, exe, "clicolor_force", .redirect, .enable, debug_io_can_read_environ);
-
-    const both = addTestCase(test_step, exe, "both", .inherit, .manual, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
-    both.setEnvironmentVariable("NO_COLOR", "1");
-    both.setEnvironmentVariable("CLICOLOR_FORCE", "1");
-
-    const both_redirected = addTestCase(test_step, exe, "both", .redirect, .manual, false);
-    both_redirected.setEnvironmentVariable("NO_COLOR", "1");
-    both_redirected.setEnvironmentVariable("CLICOLOR_FORCE", "1");
-}
-
-fn addTestCase(
-    test_step: *std.Build.Step,
-    exe: *std.Build.Step.Compile,
-    test_case_name: []const u8,
-    stderr: enum { inherit, redirect },
-    run_step_color: std.Build.Step.Run.Color,
-    expected_color_enabled: bool,
-) *std.Build.Step.Run {
-    const b = test_step.owner;
-    const step_name = b.fmt("{s} {s}{s}", .{
-        exe.name,
-        test_case_name,
-        if (stderr == .redirect) "-redirect" else "",
-    });
-    const run_exe = b.addRunArtifact(exe);
-    run_exe.setName(b.fmt("run {s}", .{step_name}));
-
-    run_exe.failing_to_execute_foreign_is_an_error = false;
-    if (stderr == .redirect) run_exe.expectStdErrMatch("");
-
-    run_exe.clearEnvironment();
-    run_exe.color = run_step_color;
-
-    // Build system quirk: Currently, Run step stdout checks will also redirect stderr, so as a
-    // workaround we use a CheckFile step instead. We must also mark the Run step as having side
-    // effects, to ensure the parent stderr is inherited when not explicitly redirected.
-    run_exe.has_side_effects = true;
-    const stdout = run_exe.captureStdOut(.{});
-    const check_file = b.addCheckFile(stdout, .{ .expected_exact = if (expected_color_enabled) "true" else "false" });
-    check_file.setName(b.fmt("check {s}", .{step_name}));
-    test_step.dependOn(&check_file.step);
-
-    return run_exe;
-}
diff --git a/test/standalone/debug_io_color/main.zig b/test/standalone/debug_io_color/main.zig
deleted file mode 100644
index d9627f61792dbf38b9acf6b0e54f2ea54a138fe1..0000000000000000000000000000000000000000
--- a/test/standalone/debug_io_color/main.zig
+++ /dev/null
@@ -1,7 +0,0 @@
-const std = @import("std");
-
-pub fn main() !void {
-    const stderr = std.debug.lockStderr(&.{});
-    defer std.debug.unlockStderr();
-    try std.Io.File.stdout().writeStreamingAll(std.Options.debug_io, if (stderr.terminal_mode != .no_color) "true" else "false");
-}
-- 
2.54.0


From 5228c8902fe178834f678cb5bec12a5a32d5df2f Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 16:31:10 -0700
Subject: [PATCH 185/215] tests: use skip_foreign_checks rather than dead
 branch

Configuration logic, in general, should not try to guess whether an
executable will be able to be run on the host. This can only be
determined by trying to, and encountering failure, for example because
binfmt_misc might be installed. OS might handle illegal instruction
traps and emulate CPU features not available, etc.

skip_foreign_checks is the mechanism intended to handle this use case.
---
 test/src/ErrorTrace.zig |  2 +
 test/src/StackTrace.zig |  2 +
 test/tests.zig          | 84 +++++++++++++++++++----------------------
 3 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/test/src/ErrorTrace.zig b/test/src/ErrorTrace.zig
index b0ce8b05bb39687429ffb8eec893f254d4c4813a..d570cf406ae4d248ff106c7b304cc77eb9097eef 100644
--- a/test/src/ErrorTrace.zig
+++ b/test/src/ErrorTrace.zig
@@ -105,6 +105,7 @@ fn addCaseConfig(
     exe.bundle_ubsan_rt = false;
 
     const run = b.addRunArtifact(exe);
+    run.skip_foreign_checks = true;
     run.removeEnvironmentVariable("CLICOLOR_FORCE");
     run.setEnvironmentVariable("NO_COLOR", "1");
     run.expectExitCode(1);
@@ -116,6 +117,7 @@ fn addCaseConfig(
     };
 
     const check_run = b.addRunArtifact(self.convert_exe);
+    check_run.skip_foreign_checks = true;
     check_run.setName(annotated_case_name);
     check_run.addFileArg(run.captureStdErr(.{}));
     check_run.expectStdOutEqual(expected_stderr);
diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig
index 23938cbf1ade2733f8220bbb03612c183ad7e27a..ae2abdd21eddebbf2af40382404644de9d71277f 100644
--- a/test/src/StackTrace.zig
+++ b/test/src/StackTrace.zig
@@ -224,6 +224,7 @@ fn addCaseInstance(
     exe.bundle_ubsan_rt = false;
 
     const run = b.addRunArtifact(exe);
+    run.skip_foreign_checks = true;
     run.removeEnvironmentVariable("CLICOLOR_FORCE");
     run.setEnvironmentVariable("NO_COLOR", "1");
     run.addCheck(.{ .expect_term = term: {
@@ -234,6 +235,7 @@ fn addCaseInstance(
     run.expectStdOutEqual("");
 
     const check_run = b.addRunArtifact(self.convert_exe);
+    check_run.skip_foreign_checks = true;
     check_run.setName(annotated_case_name);
     check_run.addFileArg(run.captureStdErr(.{}));
     check_run.expectExitCode(0);
diff --git a/test/tests.zig b/test/tests.zig
index e2f62400d1d0efa4d40966263e64d4d80e0f2306..bf72b15cf3eb42ab4de671277aeb6555bd5a5867 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -2455,29 +2455,25 @@ pub fn addStackTraceTests(
     };
     stack_traces.addCases(host_cases, b.graph.host.result.os.tag);
 
-    if (b.enable_wine) {
-        const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
-        wine_cases.* = .{
-            .b = b,
-            .step = step,
-            .test_filters = test_filters,
-            .targets = wineAndCompatible32bit(b, skip_non_native),
-            .convert_exe = convert_exe,
-        };
-        stack_traces.addCases(wine_cases, .windows);
-    }
+    const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
+    wine_cases.* = .{
+        .b = b,
+        .step = step,
+        .test_filters = test_filters,
+        .targets = wineAndCompatible32bit(b, skip_non_native),
+        .convert_exe = convert_exe,
+    };
+    stack_traces.addCases(wine_cases, .windows);
 
-    if (b.enable_darling) {
-        const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
-        darling_cases.* = .{
-            .b = b,
-            .step = step,
-            .test_filters = test_filters,
-            .targets = darlingTargets(b),
-            .convert_exe = convert_exe,
-        };
-        stack_traces.addCases(darling_cases, .macos);
-    }
+    const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
+    darling_cases.* = .{
+        .b = b,
+        .step = step,
+        .test_filters = test_filters,
+        .targets = darlingTargets(b),
+        .convert_exe = convert_exe,
+    };
+    stack_traces.addCases(darling_cases, .macos);
 
     return step;
 }
@@ -2510,31 +2506,27 @@ pub fn addErrorTraceTests(
     };
     error_traces.addCases(host_cases, b.graph.host.result.os.tag);
 
-    if (b.enable_wine) {
-        const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
-        wine_cases.* = .{
-            .b = b,
-            .step = step,
-            .test_filters = test_filters,
-            .targets = wineAndCompatible32bit(b, skip_non_native),
-            .optimize_modes = optimize_modes,
-            .convert_exe = convert_exe,
-        };
-        error_traces.addCases(wine_cases, .windows);
-    }
+    const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
+    wine_cases.* = .{
+        .b = b,
+        .step = step,
+        .test_filters = test_filters,
+        .targets = wineAndCompatible32bit(b, skip_non_native),
+        .optimize_modes = optimize_modes,
+        .convert_exe = convert_exe,
+    };
+    error_traces.addCases(wine_cases, .windows);
 
-    if (b.enable_darling) {
-        const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
-        darling_cases.* = .{
-            .b = b,
-            .step = step,
-            .test_filters = test_filters,
-            .targets = darlingTargets(b),
-            .optimize_modes = optimize_modes,
-            .convert_exe = convert_exe,
-        };
-        error_traces.addCases(darling_cases, .macos);
-    }
+    const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
+    darling_cases.* = .{
+        .b = b,
+        .step = step,
+        .test_filters = test_filters,
+        .targets = darlingTargets(b),
+        .optimize_modes = optimize_modes,
+        .convert_exe = convert_exe,
+    };
+    error_traces.addCases(darling_cases, .macos);
 
     return step;
 }
-- 
2.54.0


From 127e2d8088a37b439ce087f2d58f544b9248dc02 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Wed, 5 Aug 2026 17:52:47 -0700
Subject: [PATCH 186/215] ability to forward third party integration arguments
 to child processes

This provides a way to forward, e.g. the `-fqemu` argument from
`zig build` to a child process during Maker execution without providing
the information to the configuration logic.
---
 lib/compiler/Maker/Step/Run.zig | 33 ++++++++++++
 lib/std/Build/Configuration.zig |  7 +++
 lib/std/Build/Serialize.zig     | 95 +++++++++++++++++++++++++++++++++
 lib/std/Build/Step/Run.zig      | 53 ++++++++++++++++++
 test/tests.zig                  |  9 ++--
 5 files changed, 193 insertions(+), 4 deletions(-)

diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig
index 7f74e76954f44e5b965955d5ff5113d07428b6a7..85087be4d06ff29c71eabebd303e9ba6077dd1f9 100644
--- a/lib/compiler/Maker/Step/Run.zig
+++ b/lib/compiler/Maker/Step/Run.zig
@@ -187,6 +187,11 @@ pub fn make(
                     man.hash.addListOfBytes(run_args);
                 }
             },
+            .enable_darling => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value),
+            .enable_qemu => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value),
+            .enable_rosetta => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value),
+            .enable_wasmtime => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value),
+            .enable_wine => thirdPartyToggle(&man.hash, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value),
         }
     }
 
@@ -351,6 +356,29 @@ pub fn make(
     step.clearFailedCommand(gpa);
 }
 
+fn thirdPartyToggle(
+    man_hash: ?*Cache.HashHelper,
+    argv_list: *std.ArrayList([]const u8),
+    conf: *const Configuration,
+    setting: bool,
+    enable: ?Configuration.String,
+    disable: ?Configuration.String,
+) void {
+    if (setting) {
+        if (enable) |string| {
+            const slice = string.slice(conf);
+            if (man_hash) |h| h.addBytesZ(slice);
+            argv_list.appendAssumeCapacity(slice);
+        }
+    } else {
+        if (disable) |string| {
+            const slice = string.slice(conf);
+            if (man_hash) |h| h.addBytesZ(slice);
+            argv_list.appendAssumeCapacity(slice);
+        }
+    }
+}
+
 /// Reads stdout of a Zig test process until a termination condition is reached:
 /// * A write fails, indicating the child unexpectedly closed stdin
 /// * A test (or a response from the test runner) times out
@@ -1535,6 +1563,11 @@ pub fn rerunInFuzzMode(
             .output_file => unreachable,
             .output_directory => unreachable,
             .passthru => unreachable,
+            .enable_darling => thirdPartyToggle(null, &argv_list, conf, graph.enable_darling, arg.prefix.value, arg.suffix.value),
+            .enable_qemu => thirdPartyToggle(null, &argv_list, conf, graph.enable_qemu, arg.prefix.value, arg.suffix.value),
+            .enable_rosetta => thirdPartyToggle(null, &argv_list, conf, graph.enable_rosetta, arg.prefix.value, arg.suffix.value),
+            .enable_wasmtime => thirdPartyToggle(null, &argv_list, conf, graph.enable_wasmtime, arg.prefix.value, arg.suffix.value),
+            .enable_wine => thirdPartyToggle(null, &argv_list, conf, graph.enable_wine, arg.prefix.value, arg.suffix.value),
         }
     }
 
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index 8337da6d2f9d44f6f3b0a96241b4478f55afe3b0..fb5b04dc0039b28850dd11817b73c2f2b597da3d 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -626,6 +626,13 @@ pub const Step = extern struct {
                 output_file,
                 output_directory,
                 passthru,
+                /// `prefix` contains the enabled string.
+                /// `suffix` contains the disabled string.
+                enable_darling,
+                enable_qemu,
+                enable_rosetta,
+                enable_wasmtime,
+                enable_wine,
             };
 
             pub const Index = IndexType(@This());
diff --git a/lib/std/Build/Serialize.zig b/lib/std/Build/Serialize.zig
index c3e9443181565196d6d922ea97f6e94f386b0f8a..995a69da87f9a6becfdb35f61683178b5e046c8b 100644
--- a/lib/std/Build/Serialize.zig
+++ b/lib/std/Build/Serialize.zig
@@ -1017,6 +1017,101 @@ fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuratio
                 .producer = .{ .value = null },
                 .generated = .{ .value = null },
             },
+            .enable_darling => |a| .{
+                .flags = .{
+                    .tag = .enable_darling,
+                    .prefix = a.enabled != null,
+                    .suffix = a.disabled != null,
+                    .basename = false,
+                    .path = false,
+                    .producer = false,
+                    .generated = false,
+                    .dep_file = false,
+                    .make_absolute = false,
+                },
+                .prefix = .{ .value = try s.addOptionalString(a.enabled) },
+                .suffix = .{ .value = try s.addOptionalString(a.disabled) },
+                .basename = .{ .value = null },
+                .path = .{ .value = null },
+                .producer = .{ .value = null },
+                .generated = .{ .value = null },
+            },
+            .enable_qemu => |a| .{
+                .flags = .{
+                    .tag = .enable_qemu,
+                    .prefix = a.enabled != null,
+                    .suffix = a.disabled != null,
+                    .basename = false,
+                    .path = false,
+                    .producer = false,
+                    .generated = false,
+                    .dep_file = false,
+                    .make_absolute = false,
+                },
+                .prefix = .{ .value = try s.addOptionalString(a.enabled) },
+                .suffix = .{ .value = try s.addOptionalString(a.disabled) },
+                .basename = .{ .value = null },
+                .path = .{ .value = null },
+                .producer = .{ .value = null },
+                .generated = .{ .value = null },
+            },
+            .enable_rosetta => |a| .{
+                .flags = .{
+                    .tag = .enable_rosetta,
+                    .prefix = a.enabled != null,
+                    .suffix = a.disabled != null,
+                    .basename = false,
+                    .path = false,
+                    .producer = false,
+                    .generated = false,
+                    .dep_file = false,
+                    .make_absolute = false,
+                },
+                .prefix = .{ .value = try s.addOptionalString(a.enabled) },
+                .suffix = .{ .value = try s.addOptionalString(a.disabled) },
+                .basename = .{ .value = null },
+                .path = .{ .value = null },
+                .producer = .{ .value = null },
+                .generated = .{ .value = null },
+            },
+            .enable_wasmtime => |a| .{
+                .flags = .{
+                    .tag = .enable_wasmtime,
+                    .prefix = a.enabled != null,
+                    .suffix = a.disabled != null,
+                    .basename = false,
+                    .path = false,
+                    .producer = false,
+                    .generated = false,
+                    .dep_file = false,
+                    .make_absolute = false,
+                },
+                .prefix = .{ .value = try s.addOptionalString(a.enabled) },
+                .suffix = .{ .value = try s.addOptionalString(a.disabled) },
+                .basename = .{ .value = null },
+                .path = .{ .value = null },
+                .producer = .{ .value = null },
+                .generated = .{ .value = null },
+            },
+            .enable_wine => |a| .{
+                .flags = .{
+                    .tag = .enable_wine,
+                    .prefix = a.enabled != null,
+                    .suffix = a.disabled != null,
+                    .basename = false,
+                    .path = false,
+                    .producer = false,
+                    .generated = false,
+                    .dep_file = false,
+                    .make_absolute = false,
+                },
+                .prefix = .{ .value = try s.addOptionalString(a.enabled) },
+                .suffix = .{ .value = try s.addOptionalString(a.disabled) },
+                .basename = .{ .value = null },
+                .path = .{ .value = null },
+                .producer = .{ .value = null },
+                .generated = .{ .value = null },
+            },
         });
     }
     return result;
diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig
index 564dd2507dca28de63f943054b787c8602cc4f86..7d271e10e1461606574b96a6966332975b39b706 100644
--- a/lib/std/Build/Step/Run.zig
+++ b/lib/std/Build/Step/Run.zig
@@ -151,6 +151,19 @@ pub const Arg = union(enum) {
     output_directory: *Output,
     /// The arguments passed after "--" on the "zig build" CLI.
     passthru,
+
+    enable_darling: ToggleFlags,
+    enable_qemu: ToggleFlags,
+    enable_rosetta: ToggleFlags,
+    enable_wasmtime: ToggleFlags,
+    enable_wine: ToggleFlags,
+};
+
+pub const ToggleFlags = struct {
+    /// The string to pass when enabled, or null to omit the arg.
+    enabled: ?[]const u8 = null,
+    /// The string to pass when disabled, or null to omit the arg.
+    disabled: ?[]const u8 = null,
 };
 
 pub const DecoratedArtifact = struct {
@@ -578,6 +591,46 @@ pub fn addPassthruArgs(run: *Run) void {
     run.argv.append(arena, .passthru) catch @panic("OOM");
 }
 
+/// Appends a custom string to the command line depending on the `-fdarling`
+/// value passed to `zig build`.
+pub fn addThirdPartyEnabledArgDarling(run: *Run, toggle_flags: ToggleFlags) void {
+    const graph = run.step.owner.graph;
+    const arena = graph.arena;
+    run.argv.append(arena, .{ .enable_darling = toggle_flags }) catch @panic("OOM");
+}
+
+/// Appends a custom string to the command line depending on the `-fqemu`
+/// value passed to `zig build`.
+pub fn addThirdPartyEnabledArgQemu(run: *Run, toggle_flags: ToggleFlags) void {
+    const graph = run.step.owner.graph;
+    const arena = graph.arena;
+    run.argv.append(arena, .{ .enable_qemu = toggle_flags }) catch @panic("OOM");
+}
+
+/// Appends a custom string to the command line depending on the `-frosetta`
+/// value passed to `zig build`.
+pub fn addThirdPartyEnabledArgRosetta(run: *Run, toggle_flags: ToggleFlags) void {
+    const graph = run.step.owner.graph;
+    const arena = graph.arena;
+    run.argv.append(arena, .{ .enable_rosetta = toggle_flags }) catch @panic("OOM");
+}
+
+/// Appends a custom string to the command line depending on the `-fwasmtime`
+/// value passed to `zig build`.
+pub fn addThirdPartyEnabledArgWasmtime(run: *Run, toggle_flags: ToggleFlags) void {
+    const graph = run.step.owner.graph;
+    const arena = graph.arena;
+    run.argv.append(arena, .{ .enable_wasmtime = toggle_flags }) catch @panic("OOM");
+}
+
+/// Appends a custom string to the command line depending on the `-fwine`
+/// value passed to `zig build`.
+pub fn addThirdPartyEnabledArgWine(run: *Run, toggle_flags: ToggleFlags) void {
+    const graph = run.step.owner.graph;
+    const arena = graph.arena;
+    run.argv.append(arena, .{ .enable_wine = toggle_flags }) catch @panic("OOM");
+}
+
 pub fn setStdIn(run: *Run, stdin: StdIn) void {
     switch (stdin) {
         .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),
diff --git a/test/tests.zig b/test/tests.zig
index bf72b15cf3eb42ab4de671277aeb6555bd5a5867..44fefc69357840c351979e7cd6551e43342f0298 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -3409,10 +3409,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons
 
             run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc
 
-            if (b.enable_qemu) run.addArg("-fqemu");
-            if (b.enable_wine) run.addArg("-fwine");
-            if (b.enable_wasmtime) run.addArg("-fwasmtime");
-            if (b.enable_darling) run.addArg("-fdarling");
+            run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" });
+            run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" });
+            run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" });
+            run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" });
+            run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" });
 
             run.addCheck(.{ .expect_term = .{ .exited = 0 } });
             test_step.dependOn(&run.step);
-- 
2.54.0


From d3a7e7528dc424d689e696ce04d2b7ef5f663142 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Thu, 6 Aug 2026 18:55:02 -0700
Subject: [PATCH 187/215] stack trace tests: this check runs on host always

---
 test/src/StackTrace.zig | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig
index ae2abdd21eddebbf2af40382404644de9d71277f..7270ef4cbbe51af44efab1f4950d660554889920 100644
--- a/test/src/StackTrace.zig
+++ b/test/src/StackTrace.zig
@@ -1,3 +1,12 @@
+const StackTrace = @This();
+
+const builtin = @import("builtin");
+
+const std = @import("std");
+const Step = std.Build.Step;
+const OptimizeMode = std.lang.OptimizeMode;
+const mem = std.mem;
+
 b: *std.Build,
 step: *Step,
 test_filters: []const []const u8,
@@ -45,7 +54,7 @@ fn addCaseTarget(
     triple: ?[]const u8,
 ) void {
     const both_backends = b: {
-        if (comptime builtin.cpu.arch.endian() == .big) break :b false; // https://github.com/ziglang/zig/issues/25961
+        if (builtin.cpu.arch.endian() == .big) break :b false; // https://codeberg.org/ziglang/zig/issues/31522
         break :b switch (target.result.cpu.arch) {
             .x86_64 => switch (target.result.ofmt) {
                 .elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos,
@@ -235,7 +244,6 @@ fn addCaseInstance(
     run.expectStdOutEqual("");
 
     const check_run = b.addRunArtifact(self.convert_exe);
-    check_run.skip_foreign_checks = true;
     check_run.setName(annotated_case_name);
     check_run.addFileArg(run.captureStdErr(.{}));
     check_run.expectExitCode(0);
@@ -243,10 +251,3 @@ fn addCaseInstance(
 
     self.step.dependOn(&check_run.step);
 }
-
-const StackTrace = @This();
-const std = @import("std");
-const builtin = @import("builtin");
-const Step = std.Build.Step;
-const OptimizeMode = std.builtin.OptimizeMode;
-const mem = std.mem;
-- 
2.54.0


From d9d308f6241e6b3add34429cc2e8698c6d17c635 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Thu, 6 Aug 2026 20:21:53 -0700
Subject: [PATCH 188/215] Maker: skipped steps skip dependants too

---
 lib/compiler/Maker.zig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index 869471d4e921856cee4fd870c299a95aa0fd5965..f949ac591a951a2f7ac5bc8fe5b5a672c85d4413 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -2581,9 +2581,10 @@ fn makeStep(
                 .failure,
                 .dependency_failure,
                 .skipped_oom,
+                .skipped,
                 => break .dependency_failure,
 
-                .success, .skipped => {},
+                .success => {},
             }
         } else if (Step.make(step_index, maker, step_prog_node)) state: {
             break :state .success;
-- 
2.54.0


From 750294aa1f87815e23bac1f3e6e287cf9fa88705 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Thu, 6 Aug 2026 20:27:23 -0700
Subject: [PATCH 189/215] Maker: introduce transitive_skip

---
 lib/compiler/Maker.zig      | 21 ++++++++++++++++-----
 lib/compiler/Maker/Step.zig |  3 +++
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index f949ac591a951a2f7ac5bc8fe5b5a672c85d4413..d0d36f62ce2c0d36aac774392edce182ed621d4a 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -2119,7 +2119,7 @@ fn markFailedStepsDirty(maker: *Maker) void {
     for (all_steps) |step_index| {
         const step = maker.stepByIndex(step_index);
         switch (step.state) {
-            .dependency_failure, .failure, .skipped => _ = maker.invalidateResult(step),
+            .dependency_failure, .dependency_skipped, .failure, .skipped => _ = maker.invalidateResult(step),
             else => continue,
         }
     }
@@ -2334,7 +2334,7 @@ fn makeSteps(
             .precheck_unstarted => unreachable,
             .precheck_started => unreachable,
             .precheck_done => unreachable,
-            .dependency_failure => pending_count += 1,
+            .dependency_failure, .dependency_skipped => pending_count += 1,
             .success => success_count += 1,
             .skipped, .skipped_oom => skipped_count += 1,
             .failure => {
@@ -2580,9 +2580,12 @@ fn makeStep(
 
                 .failure,
                 .dependency_failure,
+                => break .dependency_failure,
+
+                .dependency_skipped,
                 .skipped_oom,
                 .skipped,
-                => break .dependency_failure,
+                => break .dependency_skipped,
 
                 .success => {},
             }
@@ -2603,11 +2606,12 @@ fn makeStep(
 
             .failure,
             .dependency_failure,
+            .dependency_skipped,
             .skipped_oom,
+            .skipped,
             => false,
 
             .success,
-            .skipped,
             => true,
         };
 
@@ -2624,7 +2628,7 @@ fn makeStep(
                 .precheck_done => unreachable,
                 .success => .success,
                 .failure, .dependency_failure => .failure,
-                .skipped => .skipped,
+                .dependency_skipped, .skipped => .skipped,
                 .skipped_oom => .skipped_oom,
             };
             serveBuildStepCompleted(
@@ -2778,6 +2782,12 @@ fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr:
             try stderr.setColor(.reset);
         },
 
+        .dependency_skipped => {
+            try stderr.setColor(.dim);
+            try writer.writeAll(" transitive skip\n");
+            try stderr.setColor(.reset);
+        },
+
         .success => {
             try stderr.setColor(.green);
             if (s.result_cached) {
@@ -3024,6 +3034,7 @@ fn constructGraphAndCheckForDependencyLoop(
 
         // These don't happen until we actually run the step graph.
         .dependency_failure => unreachable,
+        .dependency_skipped => unreachable,
         .success => unreachable,
         .failure => unreachable,
         .skipped => unreachable,
diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig
index b8c5992cce243ed5b7f5fb0cdfc1b6b9d92f7fdb..181cdf2bd75fc678fc45d72cbab16a9e9bbeecd1 100644
--- a/lib/compiler/Maker/Step.zig
+++ b/lib/compiler/Maker/Step.zig
@@ -163,6 +163,9 @@ pub const State = enum {
     /// be re-evaluated.
     precheck_done,
     dependency_failure,
+    /// Handled exactly the same as `dependency_failure` except communicates
+    /// that the dependency didn't fail but rather was skipped.
+    dependency_skipped,
     success,
     failure,
     /// This state indicates that the step did not complete, however, it also did not fail,
-- 
2.54.0


From eff54d672b863c46c3df7f7bbc7239dd585e83f8 Mon Sep 17 00:00:00 2001
From: Tapir 
Date: Fri, 7 Aug 2026 20:33:51 +0200
Subject: [PATCH 190/215] docs: Remove the unused native_endian declaration
 from test_packed_structs.zig (#36425)

Co-authored-by: lx 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36425
---
 doc/langref/test_packed_structs.zig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/doc/langref/test_packed_structs.zig b/doc/langref/test_packed_structs.zig
index 1fe918eefa23500a409d6228fbe789768de21564..eec2f58b10a10e4f7964a839d0b4b86e7b35da26 100644
--- a/doc/langref/test_packed_structs.zig
+++ b/doc/langref/test_packed_structs.zig
@@ -1,5 +1,4 @@
 const std = @import("std");
-const native_endian = @import("builtin").target.cpu.arch.endian();
 const expectEqual = std.testing.expectEqual;
 
 const Full = packed struct {
-- 
2.54.0


From 0f1c478db329c4b91c3a34aed2d48e4cde059eff Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 7 Aug 2026 12:32:58 -0700
Subject: [PATCH 191/215] tests: remove "compiler has package manager" logic

This is simplified now that package fetching is moved to Maker
executable.
---
 test/tests.zig | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/test/tests.zig b/test/tests.zig
index 44fefc69357840c351979e7cd6551e43342f0298..d165597131204537abc2c494a97885c3866a5e5f 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -2531,12 +2531,6 @@ pub fn addErrorTraceTests(
     return step;
 }
 
-fn compilerHasPackageManager(b: *std.Build) bool {
-    // We can only use dependencies if the compiler was built with support for package management.
-    // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
-    return b.available_deps.len != 0;
-}
-
 pub fn addStandaloneTests(
     b: *std.Build,
     optimize_modes: []const OptimizeMode,
@@ -2545,21 +2539,19 @@ pub fn addStandaloneTests(
     enable_symlinks_windows: bool,
 ) *Step {
     const step = b.step("test-standalone", "Run the standalone tests");
-    if (compilerHasPackageManager(b)) {
-        const test_cases_dep_name = "standalone_test_cases";
-        const test_cases_dep = b.dependency(test_cases_dep_name, .{
-            .enable_ios_sdk = enable_ios_sdk,
-            .enable_macos_sdk = enable_macos_sdk,
-            .enable_symlinks_windows = enable_symlinks_windows,
-            .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
-            .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
-            .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
-            .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
-        });
-        const test_cases_dep_step = test_cases_dep.builder.default_step;
-        test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
-        step.dependOn(test_cases_dep.builder.default_step);
-    }
+    const test_cases_dep_name = "standalone_test_cases";
+    const test_cases_dep = b.dependency(test_cases_dep_name, .{
+        .enable_ios_sdk = enable_ios_sdk,
+        .enable_macos_sdk = enable_macos_sdk,
+        .enable_symlinks_windows = enable_symlinks_windows,
+        .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null,
+        .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null,
+        .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null,
+        .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null,
+    });
+    const test_cases_dep_step = test_cases_dep.builder.default_step;
+    test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name);
+    step.dependOn(test_cases_dep.builder.default_step);
     return step;
 }
 
-- 
2.54.0


From 8b2949e372e615886b9087b06187878452421724 Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 7 Aug 2026 13:28:16 -0700
Subject: [PATCH 192/215] simplify stack trace and error trace tests

by explicitly listing out the combinations of parameters we would like
to check.
---
 test/error_traces.zig   |  43 +++++++-
 test/src/ErrorTrace.zig | 169 ++++++++++++++++++++---------
 test/src/StackTrace.zig | 234 +++++++++++++++++++++++++---------------
 test/stack_traces.zig   |  29 ++++-
 test/tests.zig          | 114 ++------------------
 5 files changed, 338 insertions(+), 251 deletions(-)

diff --git a/test/error_traces.zig b/test/error_traces.zig
index 071e4e8df53b7f017f988f6759db5adc30cebef0..5f84202fcfa5268094a5b625c10e30cda2bc3725 100644
--- a/test/error_traces.zig
+++ b/test/error_traces.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
+const Context = @import("tests.zig").ErrorTracesContext;
 
-pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.Os.Tag) void {
+pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void {
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "return",
         .source =
         \\pub fn main() !void {
@@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "try return",
         .source =
         \\fn foo() !void {
@@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
         },
     });
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "non-error return pops error trace",
         .source =
         \\fn bar() !void {
@@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "continue in while loop",
         .source =
         \\fn foo() !void {
@@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "for loop pops error return trace",
         .source =
         \\fn foo() !void { return error.FooError; }
@@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "implicit continue in for loop pops stale error return trace",
         .source =
         \\fn foo() !void { return error.FooError; }
@@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "while loop pops error return trace",
         .source =
         \\fn foo() !void { return error.FooError; }
@@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "implicit continue in while loop pops stale error return trace",
         .source =
         \\fn foo() !void { return error.FooError; }
@@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "try return + handled catch/if-else",
         .source =
         \\fn foo() !void {
@@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "break from inline loop pops error return trace",
         .source =
         \\fn foo() !void { return error.FooBar; }
@@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "catch and re-throw error",
         .source =
         \\fn foo() !void {
@@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "errors stored in var do not contribute to error trace",
         .source =
         \\fn foo() !void {
@@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "error stored in const has trace preserved for duration of block",
         .source =
         \\fn foo() !void { return error.TheSkyIsFalling; }
@@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "error passed to function has its trace preserved for duration of the call",
         .source =
         \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void {
@@ -418,6 +447,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "try return from within catch",
         .source =
         \\fn foo() !void {
@@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "try return from within if-else",
         .source =
         \\fn foo() !void {
@@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "try try return return",
         .source =
         \\fn foo() !void {
@@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "error union switch with call operand",
         .source =
         \\pub fn main() !void {
@@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "trace through inline call",
         // The main function has two inline calls to ensure
         // that inlinees in PDBs are properly deduplicated.
@@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
         \\}
         ,
         .expect_error = "ThisIsSoSad",
-        .expect_trace = switch (os) {
+        .expect_trace = switch (target.os.tag) {
             // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
             // so our expected result is slightly different for Windows than on other operating
             // systems.
diff --git a/test/src/ErrorTrace.zig b/test/src/ErrorTrace.zig
index d570cf406ae4d248ff106c7b304cc77eb9097eef..7fda389dc6c295a6c950f95a6551945eab878643 100644
--- a/test/src/ErrorTrace.zig
+++ b/test/src/ErrorTrace.zig
@@ -1,11 +1,81 @@
+const ErrorTrace = @This();
+
+const builtin = @import("builtin");
+
+const std = @import("std");
+const Step = std.Build.Step;
+const OptimizeMode = std.lang.Optimize;
+const mem = std.mem;
+
+const error_traces_cases = @import("../error_traces.zig");
+
 b: *std.Build,
 step: *Step,
 test_filters: []const []const u8,
-targets: []const std.Build.ResolvedTarget,
+skip_non_native: bool,
 optimize_modes: []const OptimizeMode,
 convert_exe: *std.Build.Step.Compile,
 
+pub const CaseParameters = @import("StackTrace.zig").CaseParameters;
+
+const param_sets = [_]CaseParameters{
+    .{},
+    .{
+        .link_libc = true,
+    },
+    .{
+        .use_llvm = true,
+        .use_lld = true,
+    },
+    .{
+        .pie = true,
+    },
+    .{
+        .target = .{
+            .cpu_arch = .aarch64,
+            .os_tag = .windows,
+            .abi = .msvc,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .x86_64,
+            .os_tag = .windows,
+            .abi = .gnu,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .x86,
+            .os_tag = .windows,
+            .abi = .msvc,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .aarch64,
+            .os_tag = .macos,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .s390x,
+            .os_tag = .linux,
+            .abi = .none,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .loongarch32,
+            .os_tag = .linux,
+            .abi = .none,
+        },
+    },
+};
+
 pub const Case = struct {
+    params: *const CaseParameters,
+    target: *const std.Target,
     name: []const u8,
     source: []const u8,
     expect_error: []const u8,
@@ -22,50 +92,47 @@ pub const Case = struct {
     pub const Backend = enum { llvm, selfhosted };
 };
 
-pub fn addCase(self: *ErrorTrace, case: Case) void {
-    for (self.targets) |*target| {
-        const triple: ?[]const u8 = if (target.query.isNative()) null else t: {
-            break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");
-        };
+pub fn addCases(self: *ErrorTrace) void {
+    const b = self.b;
+
+    for (¶m_sets) |*params| {
+        const resolved_target = b.resolveTargetQuery(params.target);
+
+        if (self.skip_non_native and !resolved_target.query.isNative()) continue;
+
+        // To avoid redundant testing, skip cross-compilation targets matching the host.
+        if (resolved_target.result.os.tag == builtin.target.os.tag and
+            resolved_target.result.cpu.arch == builtin.target.cpu.arch)
+        {
+            continue;
+        }
+
         for (self.optimize_modes) |optimize| {
-            self.addCaseConfig(case, target, triple, optimize, .llvm);
-        }
-        if (shouldTestNonLlvm(&target.result)) {
-            for (self.optimize_modes) |optimize| {
-                self.addCaseConfig(case, target, triple, optimize, .selfhosted);
-            }
-        }
+            if (optimize == params.optimize) break;
+        } else return;
+
+        error_traces_cases.addCases(self, params, &resolved_target.result);
     }
 }
 
-fn shouldTestNonLlvm(target: *const std.Target) bool {
-    if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961
-    return switch (target.cpu.arch) {
-        .x86_64 => switch (target.ofmt) {
-            .elf => !target.os.tag.isBSD() and target.os.tag != .illumos,
-            else => false,
-        },
-        else => false,
-    };
-}
-
-fn addCaseConfig(
-    self: *ErrorTrace,
-    case: Case,
-    target: *const std.Build.ResolvedTarget,
-    triple: ?[]const u8,
-    optimize: OptimizeMode,
-    backend: Case.Backend,
-) void {
+/// Called from test/error_traces.zig
+pub fn addCase(self: *ErrorTrace, case: Case) void {
     const b = self.b;
+    const params = case.params;
+    const target = case.target;
+    const target_query = params.target;
+
+    const triple: ?[]const u8 = if (target_query.isNative()) null else t: {
+        break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM");
+    };
 
     const error_tracing: bool = tracing: {
-        if (optimize == .debug) break :tracing true;
-        if (backend != .llvm) break :tracing true;
-        if (optimize == .small) break :tracing false;
+        if (params.optimize == .debug) break :tracing true;
+        if (params.use_llvm == false) break :tracing true;
+        if (params.optimize == .small) break :tracing false;
         for (case.disable_trace_optimized) |disable| {
             const d_arch, const d_os = disable;
-            if (target.result.cpu.arch == d_arch and target.result.os.tag == d_os) {
+            if (target.cpu.arch == d_arch and target.os.tag == d_os) {
                 // This particular configuration cannot do error tracing in optimized LLVM builds.
                 break :tracing false;
             }
@@ -73,12 +140,19 @@ fn addCaseConfig(
         break :tracing true;
     };
 
-    const annotated_case_name = b.fmt("check {s} ({s}{s}{s} {s})", .{
+    const backend_string = if (params.use_llvm == true)
+        "-llvm"
+    else if (params.use_llvm == false)
+        "-selfhosted"
+    else
+        "";
+
+    const annotated_case_name = b.fmt("check {s} ({s}{s}{t}{s})", .{
         case.name,
         triple orelse "",
         if (triple != null) " " else "",
-        @tagName(optimize),
-        @tagName(backend),
+        params.optimize,
+        backend_string,
     });
     if (self.test_filters.len > 0) {
         for (self.test_filters) |test_filter| {
@@ -92,15 +166,13 @@ fn addCaseConfig(
         .name = "test",
         .root_module = b.createModule(.{
             .root_source_file = source_zig,
-            .optimize = optimize,
-            .target = target.*,
+            .optimize = params.optimize,
+            .target = .{ .result = target.*, .query = target_query },
             .error_tracing = error_tracing,
             .strip = false,
         }),
-        .use_llvm = switch (backend) {
-            .llvm => true,
-            .selfhosted => false,
-        },
+        .use_llvm = params.use_llvm,
+        .use_lld = params.use_lld,
     });
     exe.bundle_ubsan_rt = false;
 
@@ -124,10 +196,3 @@ fn addCaseConfig(
 
     self.step.dependOn(&check_run.step);
 }
-
-const ErrorTrace = @This();
-const std = @import("std");
-const builtin = @import("builtin");
-const Step = std.Build.Step;
-const OptimizeMode = std.builtin.OptimizeMode;
-const mem = std.mem;
diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig
index 7270ef4cbbe51af44efab1f4950d660554889920..c4e4a5fe391a4141fe167681183b761c8fbf806b 100644
--- a/test/src/StackTrace.zig
+++ b/test/src/StackTrace.zig
@@ -4,16 +4,88 @@ const builtin = @import("builtin");
 
 const std = @import("std");
 const Step = std.Build.Step;
-const OptimizeMode = std.lang.OptimizeMode;
+const OptimizeMode = std.lang.Optimize;
 const mem = std.mem;
 
+const stack_traces_cases = @import("../stack_traces.zig");
+
 b: *std.Build,
 step: *Step,
 test_filters: []const []const u8,
-targets: []const std.Build.ResolvedTarget,
+skip_non_native: bool,
 convert_exe: *std.Build.Step.Compile,
 
+pub const CaseParameters = struct {
+    target: std.Target.Query = .{},
+    optimize: std.builtin.OptimizeMode = .debug,
+    link_libc: ?bool = null,
+    use_llvm: ?bool = null,
+    use_lld: ?bool = null,
+    pie: ?bool = null,
+    /// To enable this coverage, one of two things needs to happen:
+    /// * The compiler needs to gain the ability to strip only debug info (not symbols)
+    /// * `std.Build.Step.ObjCopy` needs to be un-regressed
+    strip: ?bool = false,
+};
+
+const param_sets = [_]CaseParameters{
+    .{},
+    .{
+        .link_libc = true,
+    },
+    .{
+        .use_llvm = true,
+        .use_lld = true,
+    },
+    .{
+        .pie = true,
+    },
+    .{
+        .target = .{
+            .cpu_arch = .aarch64,
+            .os_tag = .windows,
+            .abi = .msvc,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .x86_64,
+            .os_tag = .windows,
+            .abi = .gnu,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .x86,
+            .os_tag = .windows,
+            .abi = .msvc,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .aarch64,
+            .os_tag = .macos,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .s390x,
+            .os_tag = .linux,
+            .abi = .none,
+        },
+    },
+    .{
+        .target = .{
+            .cpu_arch = .loongarch32,
+            .os_tag = .linux,
+            .abi = .none,
+        },
+    },
+};
+
 const Config = struct {
+    params: *const CaseParameters,
+    target: *const std.Target,
     name: []const u8,
     source: []const u8,
     /// Whether this test case expects to have unwind tables / frame pointers.
@@ -35,42 +107,37 @@ const Config = struct {
     expect_strip: []const u8,
 };
 
+pub fn addCases(self: *StackTrace) void {
+    const b = self.b;
+
+    for (¶m_sets) |*params| {
+        const resolved_target = b.resolveTargetQuery(params.target);
+
+        if (self.skip_non_native and !resolved_target.query.isNative()) continue;
+
+        // To avoid redundant testing, skip cross-compilation targets matching the host.
+        if (resolved_target.result.os.tag == builtin.target.os.tag and
+            resolved_target.result.cpu.arch == builtin.target.cpu.arch)
+        {
+            continue;
+        }
+
+        stack_traces_cases.addCases(self, params, &resolved_target.result);
+    }
+}
+
+/// Called from test/stack_traces.zig
 pub fn addCase(self: *StackTrace, config: Config) void {
-    for (self.targets) |*target| {
-        addCaseTarget(
-            self,
-            config,
-            target,
-            if (target.query.isNative()) null else t: {
-                break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM");
-            },
-        );
-    }
-}
-fn addCaseTarget(
-    self: *StackTrace,
-    config: Config,
-    target: *const std.Build.ResolvedTarget,
-    triple: ?[]const u8,
-) void {
-    const both_backends = b: {
-        if (builtin.cpu.arch.endian() == .big) break :b false; // https://codeberg.org/ziglang/zig/issues/31522
-        break :b switch (target.result.cpu.arch) {
-            .x86_64 => switch (target.result.ofmt) {
-                .elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos,
-                else => false,
-            },
-            else => false,
-        };
+    const params = config.params;
+    const target = config.target;
+    const target_query = config.params.target;
+
+    const triple: ?[]const u8 = if (target_query.isNative()) null else t: {
+        break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM");
     };
-    const both_pie = switch (target.result.os.tag) {
-        .fuchsia => false,
-        else => true,
-    };
-    const both_libc = !std.os.targetRequiresLibC(&target.result);
 
     // See `std.debug.StackIterator.fp_usability` logic.
-    const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {
+    const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.cpu.arch) {
         .alpha,
         .csky,
         .microblaze,
@@ -92,20 +159,15 @@ fn addCaseTarget(
         .sparc,
         .sparc64,
         => .ideal,
-        .aarch64 => if (target.result.os.tag.isDarwin()) .safe else .unsafe,
+        .aarch64 => if (target.os.tag.isDarwin()) .safe else .unsafe,
         else => .unsafe,
     };
-    const supports_unwind_tables = switch (target.result.os.tag) {
+    const supports_unwind_tables = switch (target.os.tag) {
         // x86-windows just has no way to do stack unwinding other then using frame pointers.
-        .windows => target.result.cpu.arch != .x86,
+        .windows => target.cpu.arch != .x86,
         else => true,
     };
 
-    const use_llvm_vals: []const bool = if (both_backends) &.{ true, false } else &.{true};
-    const pie_vals: []const ?bool = if (both_pie) &.{ true, false } else &.{null};
-    const link_libc_vals: []const ?bool = if (both_libc) &.{ true, false } else &.{null};
-    const strip_debug_vals: []const bool = &.{ true, false };
-
     const UnwindInfo = packed struct(u2) {
         tables: bool,
         fp: bool,
@@ -135,43 +197,33 @@ fn addCaseTarget(
         },
     };
 
-    for (use_llvm_vals) |use_llvm| {
-        for (pie_vals) |pie| {
-            for (link_libc_vals) |link_libc| {
-                for (strip_debug_vals) |strip_debug| {
-                    for (unwind_info_vals) |unwind_info| {
-                        if (unwind_info.tables and !supports_unwind_tables) continue;
-                        self.addCaseInstance(
-                            target,
-                            triple,
-                            config.name,
-                            config.source,
-                            use_llvm,
-                            pie,
-                            link_libc,
-                            strip_debug,
-                            !unwind_info.tables and supports_unwind_tables,
-                            !unwind_info.fp,
-                            config.expect_panic,
-                            if (strip_debug) config.expect_strip else config.expect,
-                        );
-                    }
-                }
-            }
-        }
+    for (unwind_info_vals) |unwind_info| {
+        if (unwind_info.tables and !supports_unwind_tables) continue;
+        const strip = params.strip orelse switch (params.optimize) {
+            .debug, .fast, .safe => false,
+            .small => true,
+        };
+        self.addCaseInstance(
+            .{ .result = target.*, .query = target_query },
+            triple,
+            config.name,
+            config.source,
+            params,
+            !unwind_info.tables and supports_unwind_tables,
+            !unwind_info.fp,
+            config.expect_panic,
+            if (strip) config.expect_strip else config.expect,
+        );
     }
 }
 
 fn addCaseInstance(
     self: *StackTrace,
-    target: *const std.Build.ResolvedTarget,
+    resolved_target: std.Build.ResolvedTarget,
     triple: ?[]const u8,
     name: []const u8,
     source: []const u8,
-    use_llvm: bool,
-    pie: ?bool,
-    link_libc: ?bool,
-    strip_debug: bool,
+    params: *const CaseParameters,
     strip_unwind: bool,
     omit_frame_pointer: bool,
     expect_panic: bool,
@@ -179,13 +231,6 @@ fn addCaseInstance(
 ) void {
     const b = self.b;
 
-    if (strip_debug) {
-        // To enable this coverage, one of two things needs to happen:
-        // * The compiler needs to gain the ability to strip only debug info (not symbols)
-        // * `std.Build.Step.ObjCopy` needs to be un-regressed
-        return;
-    }
-
     if (strip_unwind) {
         // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the
         // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it
@@ -196,14 +241,28 @@ fn addCaseInstance(
         return;
     }
 
+    const backend_string = if (params.use_llvm == true)
+        " llvm"
+    else if (params.use_llvm == false)
+        " selfhosted"
+    else
+        "";
+
+    const strip_string = if (params.strip == true)
+        " strip"
+    else if (params.strip == false)
+        " unstripped"
+    else
+        "";
+
     const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{
         name,
         triple orelse "",
         if (triple != null) " " else "",
-        if (use_llvm) "llvm" else "selfhosted",
-        if (pie == true) " pie" else "",
-        if (link_libc == true) " libc" else "",
-        if (strip_debug) " strip" else "",
+        backend_string,
+        if (params.pie == true) " pie" else "",
+        if (params.link_libc == true) " libc" else "",
+        strip_string,
         if (strip_unwind) " no_unwind" else "",
         if (omit_frame_pointer) " no_fp" else "",
     });
@@ -220,16 +279,17 @@ fn addCaseInstance(
         .root_module = b.createModule(.{
             .root_source_file = source_zig,
             .optimize = .Debug,
-            .target = target.*,
+            .target = resolved_target,
             .omit_frame_pointer = omit_frame_pointer,
-            .link_libc = link_libc,
+            .link_libc = params.link_libc,
             .unwind_tables = if (strip_unwind) .none else null,
             // make panics single-threaded so that they don't include a thread ID
             .single_threaded = expect_panic,
         }),
-        .use_llvm = use_llvm,
+        .use_llvm = params.use_llvm,
+        .use_lld = params.use_lld,
     });
-    exe.pie = pie;
+    exe.pie = params.pie;
     exe.bundle_ubsan_rt = false;
 
     const run = b.addRunArtifact(exe);
@@ -238,7 +298,7 @@ fn addCaseInstance(
     run.setEnvironmentVariable("NO_COLOR", "1");
     run.addCheck(.{ .expect_term = term: {
         if (!expect_panic) break :term .{ .exited = 0 };
-        if (target.result.os.tag == .windows) break :term .{ .exited = 3 };
+        if (resolved_target.result.os.tag == .windows) break :term .{ .exited = 3 };
         break :term .{ .signal = @fromBackingInt(@intCast(6)) };
     } });
     run.expectStdOutEqual("");
diff --git a/test/stack_traces.zig b/test/stack_traces.zig
index 82d7d67863c209f4a5e3825f0eeb2cb100e50ced..352950af2b307d0fb1d7a8027358c76fe064db56 100644
--- a/test/stack_traces.zig
+++ b/test/stack_traces.zig
@@ -1,7 +1,10 @@
 const std = @import("std");
+const Context = @import("tests.zig").StackTracesContext;
 
-pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.Os.Tag) void {
+pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void {
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "simple panic",
         .source =
         \\pub fn main() void {
@@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "simple panic with no unwind strategy",
         .source =
         \\pub fn main() void {
@@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "dump current trace",
         .source =
         \\pub fn main() void {
@@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "dump current trace with no unwind strategy",
         .source =
         \\pub fn main() void {
@@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "dump captured trace",
         .source =
         \\pub fn main() void {
@@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "dump captured trace with no unwind strategy",
         .source =
         \\pub fn main() void {
@@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "dump captured trace on thread",
         .source =
         \\pub fn main() !void {
@@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
     });
 
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "simple inline panic",
         // The main function has two inline calls to ensure
         // that inlinees in PDBs are properly deduplicated.
@@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
         ,
         .unwind = .any,
         .expect_panic = true,
-        .expect = switch (os) {
+        .expect = switch (target.os.tag) {
             // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs,
             // so the first location has only a row.
             .windows =>
@@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
             \\           ^
             ,
         },
-        .expect_strip = switch (os) {
+        .expect_strip = switch (target.os.tag) {
             .windows =>
             \\panic: oh no
             \\???:?:?: [address] in source.foo
@@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
 
     // Make sure all inline calls are resolved and in the right order!
     cases.addCase(.{
+        .params = params,
+        .target = target,
         .name = "nested inline panic",
         .source =
         \\pub fn main() void {
@@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
         .unwind = .any,
         .expect_panic = true,
         // This switch serves a similar purpose as in "inline panic".
-        .expect = switch (os) {
+        .expect = switch (target.os.tag) {
             .windows =>
             \\panic: oh no
             \\source.zig:11: [address] in baz
@@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.
             \\    ^
             ,
         },
-        .expect_strip = switch (os) {
+        .expect_strip = switch (target.os.tag) {
             .windows =>
             \\panic: oh no
             \\???:?:?: [address] in baz
diff --git a/test/tests.zig b/test/tests.zig
index d165597131204537abc2c494a97885c3866a5e5f..fbb16c5a2fe759dd4840d4670670983898985276 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode;
 const Step = std.Build.Step;
 
 // Cases
-const error_traces = @import("error_traces.zig");
-const stack_traces = @import("stack_traces.zig");
 const llvm_ir = @import("llvm_ir.zig");
 const libc = @import("libc.zig");
 const link = @import("link.zig");
@@ -2381,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std
     return true;
 }
 
-/// For stack trace tests, we only test native by default, because external executors are pretty
-/// unreliable at stack tracing. However, if there's a 32-bit equivalent target which the host can
-/// trivially run, we may as well at least test that!
-fn nativeAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget {
-    const host = b.graph.host.result;
-    const only_native = (&b.graph.host)[0..1];
-    if (skip_non_native) return only_native;
-    const arch32 = compatible32bitArch(&b.graph.host.result) orelse return only_native;
-    return b.graph.arena.dupe(std.Build.ResolvedTarget, &.{
-        b.graph.host,
-        b.resolveTargetQuery(.{ .cpu_arch = arch32, .os_tag = host.os.tag }),
-    }) catch @panic("OOM");
-}
-
-fn wineAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget {
-    var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty;
-
-    const host = b.graph.host.result;
-
-    targets.append(b.graph.arena, b.resolveTargetQuery(.{
-        .cpu_arch = host.cpu.arch,
-        .os_tag = .windows,
-    })) catch @panic("OOM");
-    if (!skip_non_native) {
-        if (compatible32bitArch(&b.graph.host.result)) |arch| {
-            targets.append(b.graph.arena, b.resolveTargetQuery(.{
-                .cpu_arch = arch,
-                .os_tag = .windows,
-            })) catch @panic("OOM");
-        }
-    }
-
-    return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM");
-}
-
-fn darlingTargets(b: *std.Build) []const std.Build.ResolvedTarget {
-    var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty;
-
-    const host = b.graph.host.result;
-
-    targets.append(b.graph.arena, b.resolveTargetQuery(.{
-        .cpu_arch = host.cpu.arch,
-        .os_tag = .macos,
-    })) catch @panic("OOM");
-
-    return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM");
-}
-
-pub fn addStackTraceTests(
-    b: *std.Build,
-    test_filters: []const []const u8,
-    skip_non_native: bool,
-) *Step {
+pub fn addStackTraceTests(b: *std.Build, test_filters: []const []const u8, skip_non_native: bool) *Step {
     const step = b.step("test-stack-traces", "Run the stack trace tests");
 
     const convert_exe = b.addExecutable(.{
@@ -2445,35 +2391,15 @@ pub fn addStackTraceTests(
         }),
     });
 
-    const host_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
-    host_cases.* = .{
+    const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM");
+    stack_traces_context.* = .{
         .b = b,
         .step = step,
         .test_filters = test_filters,
-        .targets = nativeAndCompatible32bit(b, skip_non_native),
+        .skip_non_native = skip_non_native,
         .convert_exe = convert_exe,
     };
-    stack_traces.addCases(host_cases, b.graph.host.result.os.tag);
-
-    const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
-    wine_cases.* = .{
-        .b = b,
-        .step = step,
-        .test_filters = test_filters,
-        .targets = wineAndCompatible32bit(b, skip_non_native),
-        .convert_exe = convert_exe,
-    };
-    stack_traces.addCases(wine_cases, .windows);
-
-    const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
-    darling_cases.* = .{
-        .b = b,
-        .step = step,
-        .test_filters = test_filters,
-        .targets = darlingTargets(b),
-        .convert_exe = convert_exe,
-    };
-    stack_traces.addCases(darling_cases, .macos);
+    stack_traces_context.addCases();
 
     return step;
 }
@@ -2495,38 +2421,16 @@ pub fn addErrorTraceTests(
         }),
     });
 
-    const host_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
-    host_cases.* = .{
+    const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
+    error_traces_context.* = .{
         .b = b,
         .step = step,
         .test_filters = test_filters,
-        .targets = nativeAndCompatible32bit(b, skip_non_native),
+        .skip_non_native = skip_non_native,
         .optimize_modes = optimize_modes,
         .convert_exe = convert_exe,
     };
-    error_traces.addCases(host_cases, b.graph.host.result.os.tag);
-
-    const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
-    wine_cases.* = .{
-        .b = b,
-        .step = step,
-        .test_filters = test_filters,
-        .targets = wineAndCompatible32bit(b, skip_non_native),
-        .optimize_modes = optimize_modes,
-        .convert_exe = convert_exe,
-    };
-    error_traces.addCases(wine_cases, .windows);
-
-    const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM");
-    darling_cases.* = .{
-        .b = b,
-        .step = step,
-        .test_filters = test_filters,
-        .targets = darlingTargets(b),
-        .optimize_modes = optimize_modes,
-        .convert_exe = convert_exe,
-    };
-    error_traces.addCases(darling_cases, .macos);
+    error_traces_context.addCases();
 
     return step;
 }
-- 
2.54.0


From 1182f06c1487149282f699d6265e7ef91e8a56ad Mon Sep 17 00:00:00 2001
From: Brandon Black 
Date: Tue, 12 May 2026 13:22:07 -0500
Subject: [PATCH 193/215] Io: Fix Threaded.sleep(.none), doc Timeout.none

Timeout.none implicitly seems to mean indefinitely nearly
everywhere I can see.  However, Io.Threaded.sleep() has a
short-circuit at the top which treats Timeout.none as effectively
zero (no sleep at all), even though the per-target functions it
calls afterwards would otherwise would honor .none correctly.

This patch removes this (presumably erronenous) short-circuit and
documents Timeout.none's meaning explicitly.
---
 lib/std/Io.zig          | 1 +
 lib/std/Io/Threaded.zig | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index f3ef2757acad16f3dc4e548cc25d1172ba47e032..269372f12ec3a2ebc4f5dae810be15736b7dd5d4 100644
--- a/lib/std/Io.zig
+++ b/lib/std/Io.zig
@@ -1139,6 +1139,7 @@ pub const Duration = struct {
 
 /// Declares under what conditions an operation should return `error.Timeout`.
 pub const Timeout = union(enum) {
+    /// `.none` will wait forever
     none,
     duration: Clock.Duration,
     deadline: Clock.Timestamp,
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index 037fce335064106b7b8051b94d3380e3138f54d5..8180a57dc5f3a73ecf3f9425d1bc69fbdd89b25d 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -11711,7 +11711,6 @@ fn nowWasi(clock: Io.Clock) Io.Timestamp {
 
 fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void {
     const t: *Threaded = @ptrCast(@alignCast(userdata));
-    if (timeout == .none) return;
     if (use_parking_sleep) return parking_sleep.sleep(timeout);
     if (native_os == .wasi) return sleepWasi(t, timeout);
     if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout);
-- 
2.54.0


From 47825d7de3b9b26ab1dd7bca669b693bca2995e8 Mon Sep 17 00:00:00 2001
From: Brandon Black 
Date: Mon, 11 May 2026 07:34:52 -0500
Subject: [PATCH 194/215] Io.operateTimeout: if timeout == .none, operate

It's far simpler for the same effective outcome (no Batch
instantiation, no quick-success attempt + infinite poll first)
---
 lib/std/Io.zig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index 269372f12ec3a2ebc4f5dae810be15736b7dd5d4..758768634394597d57c2636ee80d62d73ee2ef38 100644
--- a/lib/std/Io.zig
+++ b/lib/std/Io.zig
@@ -466,6 +466,7 @@ pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError;
 
 /// Performs one `Operation` with provided `timeout`.
 pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result {
+    if (timeout == .none) return io.vtable.operate(io.userdata, operation);
     var storage: [1]Operation.Storage = undefined;
     var batch: Batch = .init(&storage);
     batch.addAt(0, operation);
-- 
2.54.0


From 0f332fd536aee4fcff4d0875d1d7136ba5b6f01b Mon Sep 17 00:00:00 2001
From: hemisputnik 
Date: Wed, 5 Aug 2026 06:50:26 +0300
Subject: [PATCH 195/215] std.Build.Configuration: serialize packages and their
 dependencies

The serializer now traverses the builder's available_deps and their
dependencies recursively, and serializes them into Configuration.packages.
---
 lib/compiler/Maker.zig               |  8 ++-
 lib/compiler/Maker/ScannedConfig.zig | 21 +++++++
 lib/std/Build.zig                    |  5 +-
 lib/std/Build/Configuration.zig      | 49 ++++++++++++----
 lib/std/Build/Serialize.zig          | 86 ++++++++++++++++++++++------
 5 files changed, 136 insertions(+), 33 deletions(-)

diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
index 1a3a37b6dc008e7c536ab91e505d7559addbc7bb..48acfbf33b415311606da006a27590114e3319c9 100644
--- a/lib/compiler/Maker.zig
+++ b/lib/compiler/Maker.zig
@@ -3312,17 +3312,19 @@ pub fn packagePath(
 ) Allocator.Error!Path {
     const c = &maker.scanned_config.configuration;
     const graph = maker.graph;
-    const package = package_index.get(c) orelse return .{
+
+    if (package_index == .root) return .{
         .root_dir = graph.build_root_directory,
         .sub_path = sub_path,
     };
+
     // Currently, neither configurer nor Maker is aware of the standard zig
     // package path, and the root path is stored as a bare string rather than
     // relative to a known base directory. Without changing that, we must
     // construct a cwd relative path here.
     return .{
         .root_dir = .cwd(),
-        .sub_path = try Dir.path.join(arena, &.{ package.root_path.slice(c), sub_path }),
+        .sub_path = try Dir.path.join(arena, &.{ package_index.ptr(c).root_path.slice(c), sub_path }),
     };
 }
 
@@ -3952,7 +3954,7 @@ fn confPathDepToCachePath(
             .root_dir = graph.build_root_directory,
             .sub_path = switch (path_dep.pkg.unwrap().?) {
                 .root => sub_path,
-                else => |index| try Dir.path.join(arena, &.{ index.get(c).?.root_path.slice(c), sub_path }),
+                else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }),
             },
         },
         .zig_lib => .{
diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig
index ed5661851351afb4c9a57b8723e2f4d13cd895ba..168ae8b7f61ec27abf36a4d46c2e675e982b0061 100644
--- a/lib/compiler/Maker/ScannedConfig.zig
+++ b/lib/compiler/Maker/ScannedConfig.zig
@@ -83,6 +83,27 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
         try tf.end();
     }
 
+    {
+        var tf = try s.beginTupleField("packages", .{});
+        for (c.packages) |package| {
+            var sf = try tf.beginStructField(.{});
+            try sf.field("dep_prefix", package.dep_prefix.slice(c), .{});
+            try sf.field("hash", package.hash.slice(c), .{});
+            try sf.field("root_path", package.root_path.slice(c), .{});
+
+            var dtf = try sf.beginTupleField("deps", .{});
+            for (package.deps.slice(c)) |dep| {
+                var dsf = try dtf.beginStructField(.{});
+                try sc.printStruct(&dsf, Configuration.Package.Dep, dep);
+                try dsf.end();
+            }
+            try dtf.end();
+
+            try sf.end();
+        }
+        try tf.end();
+    }
+
     try s.end();
 }
 
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index eed57a0b15b47b23b54b412c4305f12020b9773c..da2dfb4e5a7fbfc9a357347c98d5f13ab4bd8114 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -2160,7 +2160,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe
     return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args));
 }
 
-const PackageEntry = struct {
+pub const PackageEntry = struct {
     hash: []const u8,
     available: bool,
     build_root: []const u8,
@@ -2168,7 +2168,8 @@ const PackageEntry = struct {
     run_build: ?*const fn (*Build) void,
 };
 
-const package_map: std.StaticStringMap(PackageEntry) = blk: {
+/// Build system implementation detail.
+pub const package_map: std.StaticStringMap(PackageEntry) = blk: {
     const deps = @import("root").dependencies;
     const decl_names = @typeInfo(deps.packages).@"struct".decl_names;
     var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined;
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
index 3b0e6c2e7f7ee9e95bae247bb8e952850f4d9e7a..1f1da636d6ce0d64d4a22bc378d1a9c94a4a9754 100644
--- a/lib/std/Build/Configuration.zig
+++ b/lib/std/Build/Configuration.zig
@@ -15,6 +15,8 @@ unlazy_deps: []String,
 system_integrations: []SystemIntegration,
 available_options: []AvailableOption,
 search_prefixes: []String,
+/// Index 0 always exists and is the root package.
+packages: []Package,
 extra: []u32,
 default_step: Step.Index,
 generated_files_len: u32,
@@ -30,6 +32,7 @@ pub const Header = extern struct {
     system_integrations_len: u32,
     available_options_len: u32,
     search_prefixes_len: u32,
+    packages_len: u32,
     extra_len: u32,
 
     default_step: Step.Index,
@@ -58,6 +61,7 @@ pub const Wip = struct {
     steps: std.ArrayList(Step) = .empty,
     path_deps: std.ArrayList(PathDep) = .empty,
     search_prefixes: std.ArrayList(String) = .empty,
+    packages: std.ArrayList(Package) = .empty,
     extra: std.ArrayList(u32) = .empty,
     next_generated_file_index: u32 = 0,
     cache_poison: bool = false,
@@ -139,6 +143,7 @@ pub const Wip = struct {
         wip.steps.deinit(gpa);
         wip.path_deps.deinit(gpa);
         wip.search_prefixes.deinit(gpa);
+        wip.packages.deinit(gpa);
         wip.extra.deinit(gpa);
         wip.* = undefined;
     }
@@ -158,6 +163,7 @@ pub const Wip = struct {
             .system_integrations_len = @intCast(wip.system_integrations.items.len),
             .available_options_len = @intCast(wip.available_options.items.len),
             .search_prefixes_len = @intCast(wip.search_prefixes.items.len),
+            .packages_len = @intCast(wip.packages.items.len),
             .extra_len = @intCast(wip.extra.items.len),
 
             .default_step = static.default_step,
@@ -175,6 +181,7 @@ pub const Wip = struct {
             @ptrCast(wip.system_integrations.items),
             @ptrCast(wip.available_options.items),
             @ptrCast(wip.search_prefixes.items),
+            @ptrCast(wip.packages.items),
             @ptrCast(wip.extra.items),
         };
         try w.writeVecAll(&buffers);
@@ -1596,30 +1603,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) {
     }
 };
 
-pub const Package = struct {
+pub const Package = extern struct {
     dep_prefix: String,
     hash: String,
     root_path: String,
+    deps: Dep.List.Index,
 
     pub const Index = enum(u32) {
-        root = max_u32,
+        root,
         _,
 
-        /// Returns `null` for root package.
-        pub fn get(i: @This(), c: *const Configuration) ?Package {
-            if (i == .root) return null;
-            return extraData(c, Package, @backingInt(i));
+        pub fn ptr(i: @This(), c: *const Configuration) *const Package {
+            return &c.packages[@backingInt(i)];
         }
 
         pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
-            const package = get(i, c) orelse return "";
-            return package.dep_prefix.slice(c);
+            return ptr(i, c).dep_prefix.slice(c);
         }
     };
 
     pub const OptionalIndex = enum(u32) {
-        none = max_u32 - 1,
-        root = max_u32,
+        root,
+        none = max_u32,
         _,
 
         pub fn init(i: Index) OptionalIndex {
@@ -1636,6 +1641,28 @@ pub const Package = struct {
             };
         }
     };
+
+    pub const Dep = extern struct {
+        name: String,
+        /// Must not be `.root`.
+        package: Package.Index,
+
+        pub const List = struct {
+            deps: Storage.LengthPrefixedList(Dep),
+
+            pub const Index = enum(u32) {
+                _,
+
+                pub fn get(this: @This(), c: *const Configuration) List {
+                    return extraData(c, List, @backingInt(this));
+                }
+
+                pub fn slice(this: @This(), c: *const Configuration) []const Dep {
+                    return get(this, c).deps.slice;
+                }
+            };
+        };
+    };
 };
 
 pub const Module = struct {
@@ -3170,6 +3197,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
         .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len),
         .available_options = try arena.alloc(AvailableOption, header.available_options_len),
         .search_prefixes = try arena.alloc(String, header.search_prefixes_len),
+        .packages = try arena.alloc(Package, header.packages_len),
         .extra = try arena.alloc(u32, header.extra_len),
         .default_step = header.default_step,
         .generated_files_len = header.generated_files_len,
@@ -3183,6 +3211,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
         @ptrCast(result.system_integrations),
         @ptrCast(result.available_options),
         @ptrCast(result.search_prefixes),
+        @ptrCast(result.packages),
         @ptrCast(result.extra),
     };
     try reader.readVecAll(&vecs);
diff --git a/lib/std/Build/Serialize.zig b/lib/std/Build/Serialize.zig
index 72355264d978c15b712d92242df14f0c92eb4b6f..68451454c7c85b4f1fd480e65e3520251805325f 100644
--- a/lib/std/Build/Serialize.zig
+++ b/lib/std/Build/Serialize.zig
@@ -10,7 +10,8 @@ const log = std.log;
 arena: Allocator,
 wc: *Configuration.Wip,
 module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty,
-package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty,
+/// Keyed by package hash.
+package_map: std.array_hash_map.String(Configuration.Package.Index) = .empty,
 /// Index corresponds to `Configuration.steps` index.
 step_map: std.array_hash_map.Auto(*Step, void) = .empty,
 
@@ -21,6 +22,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
 
     var s: Serialize = .{ .wc = wc, .arena = arena };
 
+    // Serialize all of the packages first to seed the package_map, which is
+    // later used in calls to packageFromHash.
+    try s.addRootPackage(b);
+
     try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len);
     for (
         graph.configure_dependencies.items,
@@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
                 .relative => |r| try wc.addString(r.sub_path),
             },
             .pkg = switch (src.lazy_path) {
-                .src_path => |sp| .init(try s.builderToPackage(sp.owner)),
+                .src_path => |sp| .init(s.packageFromHash(sp.owner.pkg_hash)),
                 .generated => unreachable,
                 .cwd_relative, .relative => .none,
-                .dependency => |d| .init(try s.builderToPackage(d.dependency.builder)),
+                .dependency => |d| .init(s.packageFromHash(d.dependency.builder.pkg_hash)),
             },
         };
     }
@@ -84,7 +89,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi
             try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity);
             wc.steps.appendAssumeCapacity(.{
                 .name = try wc.addString(step.name),
-                .owner = try s.builderToPackage(step.owner),
+                .owner = s.packageFromHash(step.owner.pkg_hash),
                 .deps = deps,
                 .max_rss = .fromBytes(step.max_rss),
                 .extended = @fromBackingInt(@intCast(switch (step.tag) {
@@ -724,19 +729,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi
     }
 }
 
-fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index {
-    if (b.pkg_hash.len == 0) return .root;
+fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void {
     const arena = s.arena;
     const wc = s.wc;
-    const gop = try s.package_map.getOrPut(arena, b);
-    if (!gop.found_existing) {
-        gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{
-            .hash = try wc.addString(b.pkg_hash),
-            .dep_prefix = try wc.addString(b.dep_prefix),
-            .root_path = try wc.addString(try b.root.toString(arena)),
-        });
-    }
-    return gop.value_ptr.*;
+
+    try wc.packages.append(wc.gpa, .{
+        .dep_prefix = .empty,
+        .hash = .empty,
+        .root_path = try wc.addString(try b.root.toString(arena)),
+        .deps = undefined,
+    });
+
+    const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len);
+    for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]);
+
+    wc.packages.items[0].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
+        .deps = .{ .slice = deps },
+    });
+}
+
+fn makePackageDep(s: *Serialize, parent_dep_prefix: []const u8, name: []const u8, hash: []const u8) Allocator.Error!Configuration.Package.Dep {
+    const arena = s.arena;
+    const wc = s.wc;
+
+    if (s.package_map.get(hash)) |index| return .{
+        .name = try wc.addString(name),
+        .package = index,
+    };
+
+    const entry = std.Build.package_map.get(hash) orelse unreachable;
+
+    const dep_prefix = try arena.print("{s}{s}.", .{ parent_dep_prefix, name });
+
+    const index: Configuration.Package.Index = @fromBackingInt(@intCast(wc.packages.items.len));
+    try s.package_map.put(arena, hash, index);
+
+    try wc.packages.append(wc.gpa, .{
+        .dep_prefix = try wc.addString(dep_prefix),
+        .hash = try wc.addString(hash),
+        .root_path = try wc.addString(entry.build_root),
+        .deps = undefined,
+    });
+
+    const deps = try arena.alloc(Configuration.Package.Dep, entry.deps.len);
+    for (deps, entry.deps) |*dest, src| dest.* = try s.makePackageDep(dep_prefix, src[0], src[1]);
+
+    wc.packages.items[@backingInt(index)].deps = try wc.addExtra(Configuration.Package.Dep.List, .{
+        .deps = .{ .slice = deps },
+    });
+
+    return .{
+        .name = try wc.addString(name),
+        .package = index,
+    };
+}
+
+fn packageFromHash(s: *Serialize, pkg_hash: []const u8) Configuration.Package.Index {
+    if (pkg_hash.len == 0) return .root;
+    return s.package_map.get(pkg_hash) orelse std.debug.panic("unrecognized package hash: {q}", .{pkg_hash});
 }
 
 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
@@ -745,7 +795,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
         .src_path => |src_path| i: {
             const sub_path = try wc.addString(src_path.sub_path);
             break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
-                .owner = try s.builderToPackage(src_path.owner),
+                .owner = s.packageFromHash(src_path.owner.pkg_hash),
                 .sub_path = sub_path,
             });
         },
@@ -773,7 +823,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio
         .dependency => |dependency| i: {
             const sub_path = try wc.addString(dependency.sub_path);
             break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{
-                .owner = try s.builderToPackage(dependency.dependency.builder),
+                .owner = s.packageFromHash(dependency.dependency.builder.pkg_hash),
                 .sub_path = sub_path,
             });
         },
@@ -1138,7 +1188,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
             .link_libcpp = .init(m.link_libcpp),
             .no_builtin = .init(m.no_builtin),
         },
-        .owner = try s.builderToPackage(m.owner),
+        .owner = s.packageFromHash(m.owner.pkg_hash),
         .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
         .import_table = .invalid,
         .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
-- 
2.54.0


From 94bdde8327608af23771fbca8486c2e5c189fa1e Mon Sep 17 00:00:00 2001
From: Rue04 
Date: Sat, 8 Aug 2026 09:49:12 +0200
Subject: [PATCH 196/215] Sema: fix incorrect compile error for `@as(u32,
 @trunc(@floor(runtime_float)))`

If I had to guess, `Sema.zirRoundOpType` was probably written when `@trunc` etc. could only have a float as their destination type. As a result, for the ints they can cast to now, they'd expect the expression inside them to be a `comptime_float`, which made `@trunc(@floor(runtime_float))` or `@trunc(@floatFromInt(runtime_int))` impossible.
By changing the returned type in this case to be generic poison, showing we don't know the expected type as *any* float can be converted to an int, `@trunc(@floor(runtime_float))` lowers to effectively `@floor(runtime_float)` and `@trunc(@floatFromInt(runtime_int))` throws the expected error that `@floatFromInt`'s result type is unknown here.

Fixes: https://codeberg.org/ziglang/zig/issues/32111
Co-authored-by: rue04 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35664
---
 src/Sema.zig           | 8 ++++----
 test/behavior/cast.zig | 2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig
index c7d40ffa095a3416a65806bba49d84f6bbbc8da7..35f35d8e581d87e16335725a025a636e32ddffdf 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -25542,10 +25542,10 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
         return .generic_poison_type;
     };
 
-    const float_ty = dest_ty.optEuBaseType(zcu);
-    switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) {
-        .float, .comptime_float => return .fromType(float_ty),
-        else => return .comptime_float_type,
+    const dest_base_ty = dest_ty.optEuBaseType(zcu);
+    switch (dest_base_ty.scalarType(zcu).zigTypeTag(zcu)) {
+        .float, .comptime_float => return .fromType(dest_base_ty),
+        else => return .generic_poison_type,
     }
 }
 
diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig
index 077d3faeddc080357b48304a3f46240ad83e1fdd..2a79566b74f6fad214b6324ff3e41b5ae087ae6d 100644
--- a/test/behavior/cast.zig
+++ b/test/behavior/cast.zig
@@ -120,6 +120,7 @@ test "@floatFromInt" {
             try expect(@as(i32, @floor(f)) == k);
             try expect(@as(i32, @ceil(f)) == k);
             try expect(@as(i32, @trunc(f)) == k);
+            try expect(@as(i32, @trunc(@floor(f))) == k);
         }
     };
     try S.doTheTest();
@@ -197,6 +198,7 @@ test "@floatFromInt(f80)" {
             try expect(@as(Int, @floor(f)) == k);
             try expect(@as(Int, @ceil(f)) == k);
             try expect(@as(Int, @trunc(f)) == k);
+            try expect(@as(Int, @trunc(@floor(f))) == k);
         }
     };
     try S.doTheTest(i31);
-- 
2.54.0


From 02c49f2911674a93be7591f3d9b47bd087c0586d Mon Sep 17 00:00:00 2001
From: Rue04 
Date: Sat, 8 Aug 2026 09:54:04 +0200
Subject: [PATCH 197/215] Sema: fix crash on `@as(comptime_int,
 @floatFromInt(1))`

Fixes: https://codeberg.org/ziglang/zig/issues/32147
Co-authored-by: rue04 
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35663
Reviewed-by: mlugg 
---
 src/Sema.zig                                      | 10 ++++++++--
 test/cases/compile_errors/invalid_float_casts.zig |  2 +-
 test/cases/compile_errors/invalid_int_casts.zig   | 10 +++++++---
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig
index 35f35d8e581d87e16335725a025a636e32ddffdf..1c2c3056a5b10dd3bb5282c7ad74886d070e3efa 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -21184,7 +21184,10 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
     const dest_scalar_ty = dest_ty.scalarType(zcu);
     const operand_scalar_ty = operand_ty.scalarType(zcu);
 
-    _ = try sema.checkIntType(block, src, dest_scalar_ty);
+    switch (dest_scalar_ty.zigTypeTag(zcu)) {
+        .comptime_int, .int => {},
+        else => return sema.fail(block, src, "expected integer result type, found '{f}'", .{dest_scalar_ty.fmt(pt)}),
+    }
     try sema.checkFloatType(block, operand_src, operand_scalar_ty);
 
     if (sema.resolveValue(operand)) |operand_val| {
@@ -21360,7 +21363,10 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
     const dest_scalar_ty = dest_ty.scalarType(zcu);
     const operand_scalar_ty = operand_ty.scalarType(zcu);
 
-    try sema.checkFloatType(block, src, dest_scalar_ty);
+    switch (dest_scalar_ty.zigTypeTag(zcu)) {
+        .comptime_float, .float => {},
+        else => return sema.fail(block, src, "expected float result type, found '{f}'", .{dest_scalar_ty.fmt(pt)}),
+    }
     _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);
 
     if (sema.resolveValue(operand)) |operand_val| {
diff --git a/test/cases/compile_errors/invalid_float_casts.zig b/test/cases/compile_errors/invalid_float_casts.zig
index f6d077d8a0d370618f41e04c6e63c51f8c11908c..cc2039cea3b05d2c72d9bd09807bb75ab4b79701 100644
--- a/test/cases/compile_errors/invalid_float_casts.zig
+++ b/test/cases/compile_errors/invalid_float_casts.zig
@@ -22,6 +22,6 @@ export fn qux() void {
 // error
 //
 // :4:40: error: unable to cast runtime value to 'comptime_float'
-// :9:18: error: expected integer type, found 'f32'
+// :9:18: error: expected integer result type, found 'f32'
 // :14:32: error: expected integer type, found 'f32'
 // :19:29: error: expected float or vector type, found 'u32'
diff --git a/test/cases/compile_errors/invalid_int_casts.zig b/test/cases/compile_errors/invalid_int_casts.zig
index b2c542d0f7697ac0543b4a59ff05bacfd5ca5693..479390c5c3fb9303b5b76968d5b9b8d6d1367f96 100644
--- a/test/cases/compile_errors/invalid_int_casts.zig
+++ b/test/cases/compile_errors/invalid_int_casts.zig
@@ -8,6 +8,9 @@ export fn bar() void {
     _ = &a;
     _ = @as(u32, @floatFromInt(a));
 }
+export fn bar2() void {
+    _ = @as(comptime_int, @floatFromInt(2));
+}
 export fn baz() void {
     var a: u32 = 2;
     _ = &a;
@@ -22,6 +25,7 @@ export fn qux() void {
 // error
 //
 // :4:36: error: unable to cast runtime value to 'comptime_int'
-// :9:18: error: expected float type, found 'u32'
-// :14:32: error: expected float type, found 'u32'
-// :19:27: error: expected integer or vector, found 'f32'
+// :9:18: error: expected float result type, found 'u32'
+// :12:27: error: expected float result type, found 'comptime_int'
+// :17:32: error: expected float type, found 'u32'
+// :22:27: error: expected integer or vector, found 'f32'
-- 
2.54.0


From 637504176bd3b9a2374fc9f7f2e759ead35ac9b5 Mon Sep 17 00:00:00 2001
From: Michael Farber Brodsky 
Date: Sat, 8 Aug 2026 10:21:31 +0200
Subject: [PATCH 198/215] Sema: handle OPV types in `zirSelect` and
 `analyzeShuffle`

Fixes: https://codeberg.org/ziglang/zig/issues/35969
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35996
Reviewed-by: mlugg 
---
 src/Sema.zig              |  7 ++++++-
 test/behavior/select.zig  | 14 ++++++++++++++
 test/behavior/shuffle.zig | 20 ++++++++++++++++++++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/Sema.zig b/src/Sema.zig
index 1c2c3056a5b10dd3bb5282c7ad74886d070e3efa..c10b69fea8b0d5300d33bdbaa83f390ed463d89b 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -23547,7 +23547,9 @@ fn analyzeShuffle(
         // `InternPool.Index` values using the known operands.
         for (mask_shuffle_two, mask_ip_index) |in, *out| {
             const val: Value = switch (in.unwrap()) {
-                .undef => try pt.undefValue(elem_ty),
+                // Special case zero bit types: there is no undefined value for OPV elements.
+                // Only affects the case where `!a_rt and !b_rt` since `a_coerced` and `b_coerced`'s types are also OPV for OPV elements.
+                .undef => try elem_ty.onePossibleValue(pt) orelse try pt.undefValue(elem_ty),
                 .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx),
                 .b_elem => |idx| try maybe_b_val.?.elemValue(pt, idx),
             };
@@ -23596,6 +23598,9 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
     const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src);
     const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src);
 
+    // special case zero bit types
+    if (try vec_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
+
     const maybe_pred = sema.resolveValue(pred);
     const maybe_a = sema.resolveValue(a);
     const maybe_b = sema.resolveValue(b);
diff --git a/test/behavior/select.zig b/test/behavior/select.zig
index f3a8eda1416e62e69db9e5d4c620c77df8070e20..0bac089d7be2db12da742b2b45b8141075805e38 100644
--- a/test/behavior/select.zig
+++ b/test/behavior/select.zig
@@ -31,6 +31,20 @@ fn selectVectors() !void {
     _ = .{ &x, &y, &z };
     const xyz = @select(f32, x, y, z);
     try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
+
+    var vec_u0: @Vector(4, u0) = @splat(0);
+    var mask_u0 = @Vector(4, bool){ true, false, true, false };
+    var mask_empty = @Vector(0, i32){};
+    var vec_empty = @Vector(0, i32){};
+    _ = .{ &vec_u0, &mask_u0, &mask_empty, &vec_empty };
+    const sel_u0 = @select(u0, mask_u0, vec_u0, vec_u0);
+    const sel_u0_undefined = @select(u0, mask_u0, undefined, undefined);
+    comptime if (sel_u0[0] != 0) unreachable;
+    comptime if (sel_u0_undefined[1] != 0) unreachable;
+    const sel_empty = @select(i32, mask_empty, vec_empty, vec_empty);
+    const sel_empty_undefined = @select(i32, @Vector(0, bool){}, undefined, undefined);
+    comptime if (@as(u0, @bitCast(sel_empty)) != 0) unreachable;
+    comptime if (@as(u0, @bitCast(sel_empty_undefined)) != 0) unreachable;
 }
 
 test "@select arrays" {
diff --git a/test/behavior/shuffle.zig b/test/behavior/shuffle.zig
index 871852111025055a87858b65656ad15dc27062fe..e61e8f17a8d940c94b054228894bf6d799aa4c8d 100644
--- a/test/behavior/shuffle.zig
+++ b/test/behavior/shuffle.zig
@@ -170,3 +170,23 @@ test "@shuffle bool 2" {
     try S.doTheTest();
     try comptime S.doTheTest();
 }
+
+test "@shuffle u0" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
+
+    const S = struct {
+        fn doTheTest() !void {
+            var v: @Vector(4, u0) = @splat(0);
+            const mask = @Vector(4, i32){ undefined, 0, -1, 3 };
+            _ = .{ &v, &mask };
+            const res = @shuffle(u0, v, v, mask);
+            comptime if (!std.mem.eql(u0, &@as([4]u0, res), &[4]u0{ 0, 0, 0, 0 })) unreachable;
+        }
+    };
+    try S.doTheTest();
+    try comptime S.doTheTest();
+}
-- 
2.54.0


From cc6f42302a1cf768710d4888ce41004ef470d130 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sat, 8 Aug 2026 13:45:22 +0200
Subject: [PATCH 199/215] std.os.linux: fix F.{SETSIG,GETSIG} values for
 non-hppa architectures

closes https://codeberg.org/ziglang/zig/issues/36432
---
 lib/std/os/linux.zig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 8fd3fca48e788610aa574ced6d7c7c56a90c0568..2df4fdf75d80e01ca25cb6bb6ea94664709a0a8c 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -2058,8 +2058,8 @@ pub const F = struct {
         },
     };
 
-    pub const SETSIG = if (is_hppa or native_arch == .alpha) 13 else 11;
-    pub const GETSIG = if (is_hppa or native_arch == .alpha) 14 else 12;
+    pub const SETSIG = if (is_hppa) 13 else 10;
+    pub const GETSIG = if (is_hppa) 14 else 11;
 
     pub const SETOWN_EX = 15;
     pub const GETOWN_EX = 16;
-- 
2.54.0


From 2785bc38239a5bec644758ffa6af5523eb0fea6f Mon Sep 17 00:00:00 2001
From: agave 
Date: Fri, 7 Aug 2026 12:52:12 -0400
Subject: [PATCH 200/215] llvm: workaround to export associated .kd symbol for
 kernels on amdgcn

---
 src/codegen/llvm.zig | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 255b2f6bb38d215ce826b67ca2d6b71d38c45de5..8f3e3917fc0bf0a15dbaa5261dd9dcac9fd4f972 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1507,7 +1507,7 @@ pub const Object = struct {
         }
 
         const arch = comp.root_mod.resolved_target.result.cpu.arch;
-        const is_nvptx = arch == .nvptx or arch == .nvptx64;
+        const workaround_alias_bugs = arch == .amdgcn or arch == .nvptx or arch == .nvptx64;
 
         const llvm_global_ty = llvm_global.typeOf(&o.builder);
 
@@ -1528,10 +1528,11 @@ pub const Object = struct {
             // alias will be set below.
             const alias_global: Builder.Global.Index = global: {
 
-                // WORKAROUND (see https://github.com/llvm/llvm-project/issues/213504)
-                // LLVM throws "NVPTX aliasee must be a non-kernel function definition"
-                // if we try to alias a kernel, so we just rename the global directly.
-                if (is_nvptx and export_i == 0) {
+                // WORKAROUND (see https://github.com/llvm/llvm-project/issues/213504, https://github.com/llvm/llvm-project/issues/214835)
+                // For NVPTX, LLVM throws "NVPTX aliasee must be a non-kernel function definition" if we try to alias a kernel
+                // On AMDGCN, LLVM does not generate an alias for the kernel descriptor symbol on associated functions
+                // To solve these, we rename the global
+                if (workaround_alias_bugs and export_i == 0) {
                     try llvm_global.rename(exp_name, &o.builder);
                     break :global llvm_global;
                 }
-- 
2.54.0


From c9c97ee845459f416f7132f4d381301072315baa Mon Sep 17 00:00:00 2001
From: Perry Fraser 
Date: Fri, 7 Aug 2026 21:54:47 -0400
Subject: [PATCH 201/215] Fix tryLockStderr compilation error

Fixes #36430. Thanks to kavika13 for the suggested fix!
---
 lib/std/Io.zig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index d438208c4685453e766c0eff150cb09e747e17e7..4fcd32a0a8e7da3ba2f872ea02636f8107ff0e83 100644
--- a/lib/std/Io.zig
+++ b/lib/std/Io.zig
@@ -2527,7 +2527,7 @@ pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelabl
 
 /// Same as `lockStderr` but non-blocking.
 pub fn tryLockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelable!?LockedStderr {
-    const ls = (try io.vtable.tryLockStderr(io.userdata, buffer, terminal_mode)) orelse return null;
+    const ls = (try io.vtable.tryLockStderr(io.userdata, terminal_mode)) orelse return null;
     try ls.clear(buffer);
     return ls;
 }
-- 
2.54.0


From 9daad52a12deaa0bc53f9a54cfad3e5c7ae907d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Wed, 22 Jul 2026 13:24:03 +0200
Subject: [PATCH 202/215] std.os.linux.tls: export __tls_get_offset instead of
 __tls_get_addr on s390x

This needs to return the offset from TP for the variable, which will be negative
because this is TLS variant II. This ABI does not use __tls_get_addr at all, so
it's best not to even export it, as that will help catch bad code.
---
 lib/std/os/linux/tls.zig | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
index a42c44f29fe48de3383752055d7a63947ec52fd2..81ccd5cb56eb90ff1d2d9582f45c6b22630a5173 100644
--- a/lib/std/os/linux/tls.zig
+++ b/lib/std/os/linux/tls.zig
@@ -726,12 +726,14 @@ comptime {
         // function for the GD and LD models. This function is unlikely to actually be used, since
         // the linker should be able to relax every TLS access to the LE model and therefore
         // eliminate all calls to this function, but that isn't guaranteed.
-        _ = struct {
+        const Fns = struct {
             const TlsIndex = switch (native_arch) {
                 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...
                 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!
             };
-            export fn __tls_get_addr(ti: *const TlsIndex) *anyopaque {
+            fn __tls_get_addr(ti: *const TlsIndex) callconv(.c) *anyopaque {
+                comptime assert(native_arch != .s390x);
+
                 assert(ti.module == 1); // The executable's module ID is always 1
                 const tp = getThreadPointer();
                 const block: [*]u8 = switch (current_variant) {
@@ -743,6 +745,25 @@ comptime {
                 };
                 return block[@intCast(ti.offset)..];
             }
+            fn __tls_get_offset() callconv(.naked) noreturn {
+                comptime assert(native_arch == .s390x);
+
+                // We receive the module's GOT pointer in r12 and the GOT offset in r2.
+                asm volatile (
+                    \\ la %%r1, 0(%%r12, %%r2)
+                    \\ lg %%r2, 8(%%r1)
+                    \\ lgrl %%r0, %[block_size]
+                    \\ sgr %%r2, %%r0
+                    \\ br %%r14
+                    :
+                    : [block_size] "s" (&area_desc.block.size),
+                );
+            }
         };
+
+        if (native_arch == .s390x)
+            @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" })
+        else
+            @export(&Fns.__tls_get_addr, .{ .name = "__tls_get_addr" });
     }
 }
-- 
2.54.0


From 3239f672d2aa61ad0fea0f400cd7917fa354ea0f Mon Sep 17 00:00:00 2001
From: Anthon van der Neut 
Date: Thu, 23 Apr 2026 13:15:21 +0200
Subject: [PATCH 203/215] Add compare() to Io.Timestamp

this makes it possible to compare e.g. file stat results without
knowing implementation details for Timestamp
---
 lib/std/Io.zig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index 4fcd32a0a8e7da3ba2f872ea02636f8107ff0e83..b408b847ff34e1c70007d7528581b33895e216b5 100644
--- a/lib/std/Io.zig
+++ b/lib/std/Io.zig
@@ -981,6 +981,10 @@ pub const Timestamp = struct {
         const now_ts = clock.now(io);
         return t.durationTo(now_ts);
     }
+
+    pub fn compare(lhs: Timestamp, op: math.CompareOperator, rhs: Timestamp) bool {
+        return math.compare(lhs.nanoseconds, op, rhs.nanoseconds);
+    }
 };
 
 pub const Duration = struct {
-- 
2.54.0


From 8dfddf95fee5982d22512c0ac15278eabac5bcbb Mon Sep 17 00:00:00 2001
From: Andrew Kelley 
Date: Fri, 7 Aug 2026 17:52:24 -0700
Subject: [PATCH 204/215] std.meta: deprecate fieldInfo, fieldNames, fieldTypes

Technically there is one valid use case for `fieldNames` which is use
with an enum or union so that those types can be used interchangeably.
But in practice these functions are mainly abused, because the callsites
always know what kind of type it is.

This commit encourages Zig users to embrace using `@typeInfo` directly
when doing type reflection.
---
 lib/std/Build.zig                   |  4 ++--
 lib/std/enums.zig                   |  5 +++--
 lib/std/meta.zig                    | 25 ++++++++++++++++++-------
 lib/std/zig/AstGen.zig              |  4 ++--
 lib/std/zig/LibCInstallation.zig    |  2 +-
 lib/std/zig/llvm/Builder.zig        |  4 ++--
 lib/std/zig/llvm/bitcode_writer.zig |  2 +-
 lib/std/zig/system.zig              |  2 +-
 src/Air/Liveness.zig                |  6 +++---
 src/Sema.zig                        |  2 +-
 src/codegen/riscv64/encoding.zig    |  2 +-
 src/codegen/wasm/CodeGen.zig        |  2 +-
 src/codegen/x86_64/CodeGen.zig      |  2 +-
 src/link/Coff.zig                   |  2 +-
 src/print_targets.zig               |  6 +++---
 15 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 0258ce941c5fbb32bb162095d2ebec28262f6fc6..97bb40d52addfc8208693ee071c53bd50eb6c5b2 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -1109,7 +1109,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
     const type_id = comptime typeToEnum(T);
     const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {
         const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T;
-        const field_names = comptime std.meta.fieldNames(EnumType);
+        const field_names = @typeInfo(EnumType).@"enum".field_names;
         var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM");
 
         inline for (field_names) |field_name| {
@@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile
                 \\available operating systems:
                 \\
             , .{diags.os_name.?});
-            inline for (comptime std.meta.fieldNames(Target.Os.Tag)) |field_name| {
+            inline for (@typeInfo(Target.Os.Tag).@"enum".field_names) |field_name| {
                 std.debug.print(" {s}\n", .{field_name});
             }
             return error.ParseFailed;
diff --git a/lib/std/enums.zig b/lib/std/enums.zig
index 551cf71fcdd1c757b0e8a7db34fa11a93692a835..0f7439e00961485c4ce57f8a2a6286f6a2b9c818 100644
--- a/lib/std/enums.zig
+++ b/lib/std/enums.zig
@@ -33,7 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
 pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
     @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion);
     const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;
-    return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
+    const field_names = @typeInfo(E).@"enum".field_names;
+    return @Struct(.auto, null, field_names, &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
 }
 
 /// Looks up the supplied field values in the given enum type.
@@ -454,7 +455,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
                     }
                 }
             } else {
-                inline for (std.meta.fieldNames(E)) |field_name| {
+                inline for (@typeInfo(E).@"enum".field_names) |field_name| {
                     const key = @field(E, field_name);
                     if (@field(init_values, field_name)) |*v| {
                         const i = comptime Indexer.indexOf(key);
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index edc4a5c4e8eca6de0891b5435e644f0917a1ed28..f1dec9a1df078b0cf3916573c25fd5fe62bfc9ce 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -197,15 +197,17 @@ test containerLayout {
     try testing.expect(containerLayout(U3) == .@"extern");
 }
 
-/// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names`
-/// directly when you know what kind of type it is.
+/// Returns the list of declaration names of namespace types.
+///
+/// This function is only useful when the callsite does not know statically
+/// which kind of container it is.
 pub fn declarations(comptime T: type) []const [:0]const u8 {
     return switch (@typeInfo(T)) {
         .@"struct" => |info| info.decl_names,
         .@"enum" => |info| info.decl_names,
         .@"union" => |info| info.decl_names,
         .@"opaque" => |info| info.decl_names,
-        else => @compileError("Expected struct, enum, union, or opaque type, found '" ++ @typeName(T) ++ "'"),
+        else => comptime unreachable, // type lacks namespace
     };
 }
 
@@ -241,10 +243,13 @@ test declarations {
 }
 
 /// To be removed after Zig 0.17.0 is tagged.
-pub const declarationInfo = @compileError("Deprecated; use '@hasDecl' instead");
+pub const declarationInfo = @compileError("deprecated in favor of @hasDecl");
 /// To be removed after Zig 0.17.0 is tagged.
-pub const fields = @compileError("Deprecated; use 'fieldNames' and 'fieldTypes' instead");
+pub const fields = @compileError("deprecated in favor of @typeInfo");
 
+/// Deprecated in favor of `@typeInfo`.
+///
+/// To be removed after 0.17.0 is tagged.
 pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
     .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes },
     .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes },
@@ -298,13 +303,16 @@ test fieldInfo {
     try testing.expect(comptime uf.type == u8);
 }
 
+/// Deprecated in favor of `@typeInfo`.
+///
+/// To be removed after 0.17.0 is tagged.
 pub fn fieldNames(comptime T: type) []const [:0]const u8 {
     return switch (@typeInfo(T)) {
         .@"struct" => |s| s.field_names,
         .@"union" => |u| u.field_names,
         .@"enum" => |e| e.field_names,
         .error_set => |es| es.error_names.?,
-        else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
+        else => comptime unreachable,
     };
 }
 
@@ -336,11 +344,14 @@ test fieldNames {
     try testing.expectEqualSlices(u8, u1names[1], "b");
 }
 
+/// Deprecated in favor of `@typeInfo`.
+///
+/// To be removed after 0.17.0 is tagged.
 pub fn fieldTypes(comptime T: type) []const type {
     return switch (@typeInfo(T)) {
         .@"struct" => |s| s.field_types,
         .@"union" => |u| u.field_types,
-        else => @compileError("Expected struct or union type, found '" ++ @typeName(T) ++ "'"),
+        else => comptime unreachable,
     };
 }
 
diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig
index 1408f3c6f037e6e802ce1944764722955faa1fd8..c0860b71f61109a5b8dce360c1dea585d31d2b37 100644
--- a/lib/std/zig/AstGen.zig
+++ b/lib/std/zig/AstGen.zig
@@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher,
 const InnerError = error{ OutOfMemory, AnalysisFail };
 
 fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
-    const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+    const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
     try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count);
     return addExtraAssumeCapacity(astgen, extra);
 }
 
 fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
-    const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+    const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
     const extra_index: u32 = @intCast(astgen.extra.items.len);
     astgen.extra.items.len += field_count;
     setExtra(astgen, extra_index, extra);
diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig
index 6fa49a0ce985c9115495a16c862e7d6e1a9062d5..f9e0404606ee0fe503feb2b1ce096f2a8df0ddca 100644
--- a/lib/std/zig/LibCInstallation.zig
+++ b/lib/std/zig/LibCInstallation.zig
@@ -43,7 +43,7 @@ pub const FindError = error{
 pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation {
     var self: LibCInstallation = .{};
 
-    const field_names = comptime std.meta.fieldNames(LibCInstallation);
+    const field_names = @typeInfo(LibCInstallation).@"struct".field_names;
     const FoundKey = struct {
         found: bool,
         allocated: ?[]u8,
diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig
index 8376a569c45ac7191272eabbd0cb84b73b1843db..93a1e4e438b6f5ca5b312db0417f0311f9e7460b 100644
--- a/lib/std/zig/llvm/Builder.zig
+++ b/lib/std/zig/llvm/Builder.zig
@@ -9517,7 +9517,7 @@ pub const Metadata = packed struct(u32) {
             nodes: anytype,
             w: *Writer,
         ) !void {
-            const names = comptime std.meta.fieldNames(@TypeOf(nodes));
+            const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names;
 
             comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
             inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
@@ -13484,7 +13484,7 @@ fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytyp
         builder: *const Builder,
         pub fn hash(_: @This(), key: Key) u32 {
             var hasher = std.hash.Wyhash.init(std.hash.int(@backingInt(key.tag)));
-            inline for (comptime std.meta.fieldNames(@TypeOf(value))) |field_name| {
+            inline for (@typeInfo(@TypeOf(value)).@"struct".field_names) |field_name| {
                 hasher.update(std.mem.asBytes(&@field(key.value, field_name)));
             }
             return @truncate(hasher.final());
diff --git a/lib/std/zig/llvm/bitcode_writer.zig b/lib/std/zig/llvm/bitcode_writer.zig
index 98c8489172ee3960ab4502bd9ccbb360ed519735..0ee722165be0a39a2695d4f23f249c6e2a8299f0 100644
--- a/lib/std/zig/llvm/bitcode_writer.zig
+++ b/lib/std/zig/llvm/bitcode_writer.zig
@@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type {
 
                     try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len);
 
-                    const field_names = comptime std.meta.fieldNames(Abbrev);
+                    const field_names = @typeInfo(Abbrev).@"struct".field_names;
 
                     // This abbreviation might only contain literals
                     if (field_names.len == 0) return;
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 4d63d0c995024fa317bb59aca5e0fc2022c63c9b..1baa6e8cad8a996b1705219bd5a25d514ce8090f 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ
     // relying on `builtin.target`.
     const all_abis = comptime blk: {
         assert(@backingInt(Target.Abi.none) == 0);
-        const field_names = std.meta.fieldNames(Target.Abi)[1..];
+        const field_names = @typeInfo(Target.Abi).@"enum".field_names[1..];
         var array: [field_names.len]Target.Abi = undefined;
         for (field_names, 0..) |field_name, i| {
             array[i] = @field(Target.Abi, field_name);
diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig
index 520f71f313fc6e4b1a4c64860b4ce7f040391c26..3940ae27b8446d71c053e938dbbb9344b56daa7e 100644
--- a/src/Air/Liveness.zig
+++ b/src/Air/Liveness.zig
@@ -351,7 +351,7 @@ const Analysis = struct {
     extra: std.ArrayList(u32),
 
     fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 {
-        const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+        const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
         try a.extra.ensureUnusedCapacity(a.gpa, field_count);
         return addExtraAssumeCapacity(a, extra);
     }
@@ -1012,7 +1012,7 @@ fn analyzeInstBlock(
                 const block_scope = data.block_scopes.get(inst).?;
                 const num_deaths = data.live_set.count() - block_scope.live_set.count();
 
-                try a.extra.ensureUnusedCapacity(gpa, num_deaths + std.meta.fieldNames(Block).len);
+                try a.extra.ensureUnusedCapacity(gpa, num_deaths + @typeInfo(Block).@"struct".field_names.len);
                 const extra_index = a.addExtraAssumeCapacity(Block{
                     .death_count = num_deaths,
                 });
@@ -1275,7 +1275,7 @@ fn analyzeInstCondBr(
             // Write the mirrored deaths to `extra`
             const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));
             const else_death_count = @as(u32, @intCast(else_mirrored_deaths.items.len));
-            try a.extra.ensureUnusedCapacity(gpa, std.meta.fieldNames(CondBr).len + then_death_count + else_death_count);
+            try a.extra.ensureUnusedCapacity(gpa, @typeInfo(CondBr).@"struct".field_names.len + then_death_count + else_death_count);
             const extra_index = a.addExtraAssumeCapacity(CondBr{
                 .then_death_count = then_death_count,
                 .else_death_count = else_death_count,
diff --git a/src/Sema.zig b/src/Sema.zig
index c10b69fea8b0d5300d33bdbaa83f390ed463d89b..920bf997512c7c59bcca6715c7cf30c4f02e9bb1 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -34033,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air {
 }
 
 pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {
-    const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+    const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
     try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count);
     return sema.addExtraAssumeCapacity(extra);
 }
diff --git a/src/codegen/riscv64/encoding.zig b/src/codegen/riscv64/encoding.zig
index 40de9855cd342b35ea2ba540a20d589822c1b76f..5ca6a094d774fbaeb6a96c6c75ecd26a903da705 100644
--- a/src/codegen/riscv64/encoding.zig
+++ b/src/codegen/riscv64/encoding.zig
@@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) {
     extra: u32,
 
     comptime {
-        for (std.meta.fieldTypes(Instruction)) |field_type| {
+        for (@typeInfo(Instruction).@"union".field_types) |field_type| {
             assert(@bitSizeOf(field_type) == 32);
         }
     }
diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig
index 8b9b5869d85fcf498847c2fe49fb72dd7fa6232a..df15671e3379fabd3fbd3e2a75a015367b0e77a0 100644
--- a/src/codegen/wasm/CodeGen.zig
+++ b/src/codegen/wasm/CodeGen.zig
@@ -567,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v
 /// Appends entries to `mir_extra` based on the type of `extra`.
 /// Returns the index into `mir_extra`
 fn addExtra(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 {
-    const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+    const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
     try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count);
     return cg.addExtraAssumeCapacity(extra);
 }
diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig
index 9a087ca03e284f1bf751c52f77ef393a1c1c5896..063a8c158f3ff592ded65497dc14640098588e31 100644
--- a/src/codegen/x86_64/CodeGen.zig
+++ b/src/codegen/x86_64/CodeGen.zig
@@ -1301,7 +1301,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
 }
 
 fn addExtra(self: *CodeGen, extra: anytype) Allocator.Error!u32 {
-    const field_count = std.meta.fieldNames(@TypeOf(extra)).len;
+    const field_count = @typeInfo(@TypeOf(extra)).@"struct".field_names.len;
     try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count);
     return self.addExtraAssumeCapacity(extra);
 }
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 729e6393845bdcd5d8edbf98ea8fa126f718e978..78195f75241f3808610760eedb7d4b83eba681d5 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes(
         parent.name(coff).toSlice(coff),
     });
 
-    inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| {
+    inline for (@typeInfo(ObjectSectionAttributes).@"struct".field_names) |field| {
         if (@field(child_attrs, field) != @field(parent_attrs, field)) {
             err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{
                 field,
diff --git a/src/print_targets.zig b/src/print_targets.zig
index 702a684de3e829b8e7d475c265a5ed2e584caa1e..695a9a5ef4dc168b85d479f691073d4008efa3a8 100644
--- a/src/print_targets.zig
+++ b/src/print_targets.zig
@@ -43,9 +43,9 @@ pub fn cmdTargets(
     {
         var root_obj = try serializer.beginStruct(.{});
 
-        try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{});
-        try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{});
-        try root_obj.field("abi", meta.fieldNames(Target.Abi), .{});
+        try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{});
+        try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{});
+        try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{});
 
         {
             var libc_obj = try root_obj.beginTupleField("libc", .{});
-- 
2.54.0


From 6fd38ce13f4cff552272fcc33c8a23d735ac0a49 Mon Sep 17 00:00:00 2001
From: Bernard Assan 
Date: Thu, 16 Apr 2026 11:54:46 +0000
Subject: [PATCH 205/215] Use iouring probing over kernel version checks

this will enable test passing on all linux kernels (particularly WSL)
without version checks and making `skipKernelLessThan` redundant

closes https://github.com/ziglang/zig/pull/24042

Signed-off-by: Bernard Assan 
---
 lib/std/os/linux/IoUring/test.zig | 83 ++++++++++---------------------
 1 file changed, 26 insertions(+), 57 deletions(-)

diff --git a/lib/std/os/linux/IoUring/test.zig b/lib/std/os/linux/IoUring/test.zig
index 070bd4245f12cdcc48723e5db51ac72d5d74f2bf..7cfe8e3ce77af942e321888dbcf3cf3d4f20002a 100644
--- a/lib/std/os/linux/IoUring/test.zig
+++ b/lib/std/os/linux/IoUring/test.zig
@@ -475,9 +475,6 @@ test "close" {
 }
 
 test "accept/connect/send/recv" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -620,7 +617,7 @@ test "timeout (after a relative time)" {
 
     const ms = 10;
     const margin = 5;
-    const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * 1000000 };
+    const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = ms * std.time.ns_per_ms };
 
     const started = std.Io.Clock.awake.now(io);
     const sqe = try ring.timeout(0x55555555, &ts, 0, 0);
@@ -730,9 +727,6 @@ test "timeout_remove" {
 }
 
 test "accept/connect/recv/link_timeout" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" {
     const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0);
     sqe_recv.flags |= linux.IOSQE_IO_LINK;
 
-    const ts = linux.kernel_timespec{ .sec = 0, .nsec = 1000000 };
+    const ts: linux.kernel_timespec = .{ .sec = 0, .nsec = std.time.ns_per_ms };
     _ = try ring.link_timeout(0x22222222, &ts, 0);
 
     const nr_wait = try ring.submit();
@@ -883,9 +877,6 @@ test "statx" {
 }
 
 test "accept/connect/recv/cancel" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -1568,9 +1559,6 @@ test "remove_buffers" {
 }
 
 test "provide_buffers: accept/connect/send/recv" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -1777,11 +1765,6 @@ test "accept multishot" {
 }
 
 test "accept/connect/send_zc/recv" {
-    try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 });
-
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" {
     };
     defer ring.deinit();
 
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    const ops_not_supported = !probe.is_supported(.ACCEPT) or
+        !probe.is_supported(.CONNECT) or
+        !probe.is_supported(.SEND_ZC) or
+        !probe.is_supported(.RECV);
+    if (ops_not_supported) return error.SkipZigTest;
+
     const socket_test_harness = try createSocketTestHarness(&ring);
     defer socket_test_harness.close();
 
@@ -1836,14 +1826,16 @@ test "accept/connect/send_zc/recv" {
 }
 
 test "accept_direct" {
-    try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
-
     var ring = IoUring.init(1, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
         else => return err,
     };
     defer ring.deinit();
+
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
+
     var address: linux.sockaddr.in = .{
         .port = 0,
         .addr = @as(*align(1) const u32, @ptrCast(
@@ -1921,8 +1913,6 @@ test "accept_direct" {
 }
 
 test "accept_multishot_direct" {
-    try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
-
     var ring = IoUring.init(1, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -1930,6 +1920,9 @@ test "accept_multishot_direct" {
     };
     defer ring.deinit();
 
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest;
+
     var address: linux.sockaddr.in = .{
         .port = 0,
         .addr = @as(*align(1) const u32, @ptrCast(
@@ -1984,8 +1977,6 @@ test "accept_multishot_direct" {
 }
 
 test "socket" {
-    try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
-
     var ring = IoUring.init(1, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -1993,6 +1984,9 @@ test "socket" {
     };
     defer ring.deinit();
 
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    if (!probe.is_supported(.SOCKET)) return error.SkipZigTest;
+
     // prepare, submit socket operation
     _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0);
     try testing.expectEqual(@as(u32, 1), try ring.submit());
@@ -2007,8 +2001,6 @@ test "socket" {
 }
 
 test "socket_direct/socket_direct_alloc/close_direct" {
-    try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
-
     var ring = IoUring.init(2, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -2016,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {
     };
     defer ring.deinit();
 
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    if (!probe.is_supported(.SOCKET) or !probe.is_supported(.CLOSE)) return error.SkipZigTest;
+
     var registered_fds: [3]linux.fd_t = @splat(-1);
     try ring.register_files(registered_fds[0..]);
 
@@ -2090,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" {
 }
 
 test "openat_direct/close_direct" {
-    try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 });
-
     var ring = IoUring.init(2, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -2099,6 +2092,9 @@ test "openat_direct/close_direct" {
     };
     defer ring.deinit();
 
+    const probe = ring.get_probe() catch return error.SkipZigTest;
+    if (!probe.is_supported(.OPENAT) or !probe.is_supported(.CLOSE)) return error.SkipZigTest;
+
     var registered_fds: [3]linux.fd_t = @splat(-1);
     try ring.register_files(registered_fds[0..]);
 
@@ -2141,9 +2137,6 @@ test "openat_direct/close_direct" {
 }
 
 test "ring mapped buffers recv" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -2231,9 +2224,6 @@ test "ring mapped buffers recv" {
 }
 
 test "ring mapped buffers multishot recv" {
-    const io = testing.io;
-    _ = io;
-
     var ring = IoUring.init(16, 0) catch |err| switch (err) {
         error.SystemOutdated => return error.SkipZigTest,
         error.PermissionDenied => return error.SkipZigTest,
@@ -2665,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
 
     // All good
 
-    return SocketTestHarness{
+    return .{
         .listener = listener_socket,
         .server = cqe_accept.res,
         .client = client,
@@ -2688,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t {
     return listener_socket;
 }
 
-/// For use in tests. Returns SkipZigTest if kernel version is less than required.
-inline fn skipKernelLessThan(required: std.SemanticVersion) !void {
-    var uts: linux.utsname = undefined;
-    const res = linux.uname(&uts);
-    switch (linux.errno(res)) {
-        .SUCCESS => {},
-        else => |errno| return posix.unexpectedErrno(errno),
-    }
-
-    const release = mem.sliceTo(&uts.release, 0);
-    // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64"
-    const extra_index = std.mem.findAny(u8, release, "-+");
-    const stripped = release[0..(extra_index orelse release.len)];
-    // Make sure the input don't rely on the extra we just stripped
-    try testing.expect(required.pre == null and required.build == null);
-
-    var current = try std.SemanticVersion.parse(stripped);
-    current.pre = null; // don't check pre field
-    if (required.order(current) == .gt) return error.SkipZigTest;
-}
-
 fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr {
     return @ptrCast(addr);
 }
-- 
2.54.0


From c88f7285289b68aa627ad81ecccbca4fb4b62521 Mon Sep 17 00:00:00 2001
From: Ryan Liptak 
Date: Sat, 8 Aug 2026 13:42:12 -0700
Subject: [PATCH 206/215] Certificate: Fix panic/regression in EMSA_PSS_VERIFY

This logic was not properly implemented when switching to `@memmove` from `mem.copyForwards` in ab4028d5796c68ca3aeb649e475bceff394942fc

Before this commit, these lines were guaranteed to panic with `source and destination arguments have non-equal lengths`
---
 lib/std/crypto/Certificate.zig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index 3bf35280d7a250a3bc029e8797da5da1ac97e92d..974c486b1bf13a5a4a8bf7a7a9be7c37451d0267 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -1148,8 +1148,8 @@ pub const rsa = struct {
             }
             var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
             var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];
-            @memmove(m_p, @as(*const [8]u8, &@splat(0)));
-            @memmove(m_p[8..], &mHash);
+            @memmove(m_p[0..8], @as(*const [8]u8, &@splat(0)));
+            @memmove(m_p[8..][0..Hash.digest_length], &mHash);
             @memmove(m_p[(8 + Hash.digest_length)..], salt);
 
             // 13.  Let H' = Hash(M'), an octet string of length hLen.
-- 
2.54.0


From 5f2729a1a2ddbeb23ff6bd25c567d4ccd596af92 Mon Sep 17 00:00:00 2001
From: Gereon V <72784429+GereonV@users.noreply.github.com>
Date: Fri, 7 Aug 2026 13:03:06 +0200
Subject: [PATCH 207/215] Fix O_NONBLOCK bug

---
 lib/std/Io/Threaded.zig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
index bcbc1ec9cc5351ee540546ccdb72d7151a0ed2f9..eafcfb931b81bbe4a69a6bffd285c448aee8b605 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -4403,7 +4403,7 @@ fn dirCreateFilePosix(
             }
         };
 
-        fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
+        fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
 
         const syscall: Syscall = try .start();
         while (true) {
@@ -4999,7 +4999,7 @@ fn dirOpenFilePosix(
             }
         };
 
-        fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
+        fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK"));
 
         const syscall: Syscall = try .start();
         while (true) {
-- 
2.54.0


From 8e741045bc672858dfe2ca85c8253fb755afd375 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= 
Date: Sun, 9 Aug 2026 00:03:32 +0200
Subject: [PATCH 208/215] std.fs.test: disable `deleteDir` on Windows due to
 flakiness

https://codeberg.org/ziglang/zig/issues/35686
---
 lib/std/fs/test.zig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index e9c2d5f8f8e167b7556ec5eaec20d994cc2f5d73..981bc75d442a3688f43224d4dfe278c03ea3f5a8 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -939,6 +939,8 @@ test "createDirPathOpen parent dirs do not exist" {
 }
 
 test "deleteDir" {
+    if (builtin.target.os.tag == .windows) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35686
+
     try testWithAllSupportedPathTypes(struct {
         fn impl(ctx: *TestContext) !void {
             const io = ctx.io;
-- 
2.54.0


From 83b57947e328163263bb1e581bdf790bc15e8395 Mon Sep 17 00:00:00 2001
From: Matthew Lugg 
Date: Sat, 8 Aug 2026 09:38:38 +0100
Subject: [PATCH 209/215] link: don't include static libraries in other static
 libraries

Follow-up to 9aa93a045ebbf7d5c6349eb41e99ca516ab9ba65, which fixed this
bug for *shared* library inputs, but not *static* library inputs.

Supersedes https://codeberg.org/ziglang/zig/pulls/31383 by fixing the
bug at the compiler level instead of working around it in the build
system. This seems preferable because it is useful to the compiler to
have full information about a compilation's link inputs---for instance
this could interact with https://github.com/ziglang/zig/issues/20654 in
the future by having the compiler learn about a static library's ABI
even if that static library does not ultimately contribute to the link.

Resolves: https://codeberg.org/ziglang/zig/issues/35624
---
 src/link/Elf.zig   | 15 +++++++--------
 src/link/Lld.zig   |  4 ++--
 src/link/MachO.zig |  5 +++++
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 04d4f9235e12f22c3ee7f012c48d43f323ea38a1..80844d3d8832b7b326411038a286cc2391b4d097 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
     const target = self.getTarget();
     const debug_fmt_strip = comp.config.debug_format == .strip;
     const default_sym_version = self.default_sym_version;
-    const is_static_lib = self.base.isStaticLib();
 
     if (comp.verbose_link) {
         comp.mutex.lockUncancelable(io); // protect comp.arena
@@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
         .res => unreachable,
         .dso_exact => @panic("TODO"),
         .object => |obj| try parseObject(self, obj),
-        .archive => |obj| try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
+        .archive => |obj| if (self.base.isStaticLib()) {
+            // Ignore static library inputs when generating a static library.
+        } else {
+            try parseArchive(gpa, io, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj);
+        },
         .dso => |dso| try parseDso(gpa, io, diags, dso, &self.shared_objects, &self.files, target),
     }
 }
@@ -1083,7 +1086,6 @@ fn parseArchive(
     default_sym_version: elf.Versym,
     objects: *std.ArrayList(File.Index),
     obj: link.Input.Object,
-    is_static_lib: bool,
 ) !void {
     const tracy = trace(@src());
     defer tracy.end();
@@ -1092,17 +1094,14 @@ fn parseArchive(
     var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh);
     defer archive.deinit(gpa);
 
-    const init_alive = if (is_static_lib) true else obj.must_link;
-
     for (archive.objects) |extracted| {
         const index: File.Index = @intCast(try files.addOne(gpa));
         files.set(index, .{ .object = extracted });
         const object = &files.items(.data)[index].object;
         object.index = index;
-        object.alive = init_alive;
+        object.alive = obj.must_link;
         try object.parseCommon(gpa, io, diags, obj.path, obj.file, target);
-        if (!is_static_lib)
-            try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
+        try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
         try objects.append(gpa, index);
     }
 }
diff --git a/src/link/Lld.zig b/src/link/Lld.zig
index 63b1df93c0d19823843c023c0ce185083668f013..894e21785c1ff5c5a969a12acff6538c8a752e12 100644
--- a/src/link/Lld.zig
+++ b/src/link/Lld.zig
@@ -306,8 +306,8 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void {
 
     try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len);
     for (comp.link_inputs) |input| switch (input) {
-        .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives
-        .object, .archive => {
+        .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives
+        .res, .object => {
             const path = try input.path().?.toStringZ(arena);
             object_files.appendAssumeCapacity(path);
         },
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 3dddf5f78ebc396599c14c666f4b15c082fbce0f..eb94246a43fe3b4d38d2473f5d53a9512890a20a 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -992,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa
     const tracy = trace(@src());
     defer tracy.end();
 
+    if (self.base.isStaticLib()) {
+        // Ignore static library inputs when generating a static library.
+        return;
+    }
+
     const gpa = self.base.comp.gpa;
 
     var archive: Archive = .{};
-- 
2.54.0


From c9dc9b798cdf03e792c214268b1b46fbee1d6c54 Mon Sep 17 00:00:00 2001
From: Krzysztof Wolicki 
Date: Sat, 8 Aug 2026 10:54:00 +0200
Subject: [PATCH 210/215] Add missing step.clearFailedCommand to PkgConfig.run

---
 lib/compiler/Maker/PkgConfig.zig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/compiler/Maker/PkgConfig.zig b/lib/compiler/Maker/PkgConfig.zig
index 5ef34a8fbce44001dc822d37d55f11fd1a636e48..a16efae4bd60b0bf89cddef23fd99e9af304e5b6 100644
--- a/lib/compiler/Maker/PkgConfig.zig
+++ b/lib/compiler/Maker/PkgConfig.zig
@@ -63,6 +63,8 @@ pub fn run(
         }
     }
 
+    step.clearFailedCommand(maker.gpa);
+
     return parsed;
 }
 
-- 
2.54.0


From 828a5414db01df38bb2ace6034cf64330e776fd9 Mon Sep 17 00:00:00 2001
From: zirunis 
Date: Tue, 6 Jan 2026 21:31:26 +0100
Subject: [PATCH 211/215] Manually add shell command and output of
 float_mode_example.zig to langref as a workaround until autodoc supports
 linking object files

---
 doc/langref.html.in | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/langref.html.in b/doc/langref.html.in
index 1a0d531b591faabdac3d75367ababda8eafcfa6d..d1c14d15f744c99e4cf6c951bdaed77ac0ba7f3b 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1119,6 +1119,10 @@
       otherwise the optimizer figures out all the values at compile-time,
       which operates in strict mode.

{#code|float_mode_exe.zig#} + {#shell_samp#}$ zig build-exe float_mode_exe.zig float_mode_obj.o -O fast +$ ./float_mode_exe +optimized = 0.001 +strict = 0.0009765625{#end_shell_samp#} {#see_also|@setFloatMode|Division by Zero#} {#header_close#} -- 2.54.0 From 49e20bd9dd0291c40d9f24e8333449b8ecc95040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 9 Aug 2026 12:01:21 +0200 Subject: [PATCH 212/215] std.Io.Threaded: fix `fileWriteFileStreaming` error handling If the `getSize` inside `fileWriteFileStreaming` returns an error, two cases can happen: - If was canceled, it will return 0, which will make the calling function repeat it, in which case the cancellation is lost - If it truly returned an error, it will return 0, in which case the calling function will repeat the call and most likely `getSize` will fail again, resulting in an infinite loop Co-authored-by: Lukas Lalinsky Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36140 Reviewed-by: mlugg --- lib/std/Io/Threaded.zig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index eafcfb931b81bbe4a69a6bffd285c448aee8b605..715356e8d131ee9c552f1caa70e92c426b9592e7 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -11230,7 +11230,10 @@ fn fileWriteFileStreaming( var off: std.os.linux.off_t = undefined; const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) { .positional => o: { - const size = file_reader.getSize() catch return 0; + const size = file_reader.getSize() catch |err| switch (err) { + error.Canceled => |e| return e, + else => break :sf, + }; off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed; break :o .{ &off, @min(@backingInt(limit), size - file_reader.pos, max_count) }; }, @@ -11579,7 +11582,10 @@ fn fileWriteFilePositional( if (file_reader.pos != 0) break :fcf; if (offset != 0) break :fcf; if (limit != .unlimited) break :fcf; - const size = file_reader.getSize() catch break :fcf; + const size = file_reader.getSize() catch |err| switch (err) { + error.Canceled => |e| return e, + else => break :fcf, + }; if (header.len != 0 or reader_buffered.len != 0) { const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); file_reader.interface.toss(n -| header.len); -- 2.54.0 From 821d122c82af499c2a5b2fc0223cf399faa10d16 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 7 Aug 2026 03:02:58 -0400 Subject: [PATCH 213/215] bootstrap: change/enable c compiler optimizations for zig1/zig2 --- CMakeLists.txt | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14df4e9b568d8fb6c5b924f6cd4e3c9778dc5e21..ce1289ceecfab1a3fc063e923c73400bac030020 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -602,24 +602,17 @@ if(MSVC) set(ZIG2_COMPILE_FLAGS "/Od") set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE") else() - set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2") - set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing") - set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") + set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99") + set(ZIG1_COMPILE_FLAGS "-std=c99 -Oz -fno-strict-aliasing") + set(ZIG2_COMPILE_FLAGS "-std=c99 -Oz -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") + if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ZIG_HOST_TARGET_ARCH STREQUAL "s390x") + string(REPLACE -Oz -O0 ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS}") # llvm 22 assertion failure + endif() # Must match the condition in build.zig. if(ZIG_HOST_TARGET_ARCH MATCHES "^(arm|thumb)(eb)?$" OR ZIG_HOST_TARGET_ARCH EQUAL "hexagon" OR ZIG_HOST_TARGET_ARCH MATCHES "^powerpc(64)?(le)?$") set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections") set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections") endif() - if(APPLE) - set(ZIG2_LINK_FLAGS "-Wl,-stack_size,0x10000000") - elseif(MINGW) - set(ZIG2_LINK_FLAGS "-Wl,--stack,0x10000000") - # Solaris/illumos ld(1) does not provide a --stack-size option. - elseif(CMAKE_HOST_SOLARIS) - unset(ZIG2_LINK_FLAGS) - else() - set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000") - endif() if (CMAKE_C_COMPILER_ID STREQUAL "GNU") # Prevent GCC from miscompiling 'zig2.c'. See also 'GCC_BUG_119085_PRESENT' workaround details in 'bootstrap.c'. if ( -- 2.54.0 From b2c230df5033864a19eb65defceac1cc3013be3c Mon Sep 17 00:00:00 2001 From: xeondev Date: Wed, 1 Jul 2026 16:52:34 +0300 Subject: [PATCH 214/215] std.Io: change `netClose` to accept `[]const net.Socket` --- lib/std/Io.zig | 6 +++--- lib/std/Io/Dispatch.zig | 4 ++-- lib/std/Io/Kqueue.zig | 4 ++-- lib/std/Io/Threaded.zig | 8 ++++---- lib/std/Io/Uring.zig | 4 ++-- lib/std/Io/net.zig | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/std/Io.zig b/lib/std/Io.zig index b408b847ff34e1c70007d7528581b33895e216b5..ec6afd24f9553e853a1eee5897b6b0f5dd363ff2 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -238,7 +238,7 @@ pub const VTable = struct { netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize, - netClose: *const fn (?*anyopaque, handle: []const net.Socket.Handle) void, + netClose: *const fn (?*anyopaque, sockets: []const net.Socket) void, netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void, netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface, netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name, @@ -3482,9 +3482,9 @@ pub fn failingNetWriteFile(userdata: ?*anyopaque, handle: net.Socket.Handle, hea return error.NetworkDown; } -pub fn unreachableNetClose(userdata: ?*anyopaque, handle: []const net.Socket.Handle) void { +pub fn unreachableNetClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { _ = userdata; - _ = handle; + _ = sockets; unreachable; } diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig index e8595f3cbdbf24f5acfa642f3cd9ceb698a122c2..e342a0a9f9606bfd6a8dff6cc17e900fba8d2129 100644 --- a/lib/std/Io/Dispatch.zig +++ b/lib/std/Io/Dispatch.zig @@ -4912,10 +4912,10 @@ fn netWriteFileUnavailable( return error.Unimplemented; } -fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { +fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { const ev: *Evented = @ptrCast(@alignCast(userdata)); _ = ev; - for (handles) |handle| closeFd(handle); + for (sockets) |socket| closeFd(socket.handle); } fn netShutdownUnavailable( diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig index ce339f029f3a9bab3627154658bd53b6af5c14f2..ea8cbb6cad024be2fe987cc3296bd3e70006aab9 100644 --- a/lib/std/Io/Kqueue.zig +++ b/lib/std/Io/Kqueue.zig @@ -1280,10 +1280,10 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, @panic("TODO"); } -fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { +fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { const k: *Kqueue = @ptrCast(@alignCast(userdata)); _ = k; - _ = handles; + _ = sockets; @panic("TODO"); } diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 715356e8d131ee9c552f1caa70e92c426b9592e7..7a4e2640376345437afa5721b83f8ddb0d99453f 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -13415,13 +13415,13 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { i.* += 1; } -fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { +fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { if (!have_networking) unreachable; const t: *Threaded = @ptrCast(@alignCast(userdata)); _ = t; - for (handles) |handle| switch (native_os) { - .windows => windows.CloseHandle(handle), - else => closeFd(handle), + for (sockets) |socket| switch (native_os) { + .windows => windows.CloseHandle(socket.handle), + else => closeFd(socket.handle), }; } diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig index d59b2d45b461b03eafaa4ae188bb50819b2a9a2d..86f5bee4bf69329a21257fe6be0946fb0eb28153 100644 --- a/lib/std/Io/Uring.zig +++ b/lib/std/Io/Uring.zig @@ -5189,9 +5189,9 @@ fn netWriteFileUnavailable( return error.Unimplemented; } -fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { +fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { const ev: *Evented = @ptrCast(@alignCast(userdata)); - for (handles) |handle| ev.close(handle); + for (sockets) |sock| ev.close(sock.handle); } fn netShutdown( diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index 9c2e3d3a693c0cd1f5af53ee610c2a64e36ad4b3..c778dcde66f4b773a3d3f95f698c628eacb3f5f1 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -1081,7 +1081,7 @@ pub const Socket = struct { /// Leaves `address` in a valid state. pub fn close(s: *const Socket, io: Io) void { - io.vtable.netClose(io.userdata, (&s.handle)[0..1]); + io.vtable.netClose(io.userdata, s[0..1]); } pub fn closeMany(io: Io, sockets: []const Socket) void { @@ -1258,7 +1258,7 @@ pub const Stream = struct { } pub fn close(s: *const Stream, io: Io) void { - io.vtable.netClose(io.userdata, (&s.socket.handle)[0..1]); + io.vtable.netClose(io.userdata, (&s.socket)[0..1]); } pub fn shutdown(s: *const Stream, io: Io, how: ShutdownHow) ShutdownError!void { -- 2.54.0 From cb7c6e391872d2922a688c77def805883b69eba8 Mon Sep 17 00:00:00 2001 From: Anshul Gupta Date: Mon, 1 Jun 2026 16:48:12 -0700 Subject: [PATCH 215/215] std.Io.Threaded: respect options.family in netLookup Previously `AF_UNSPEC` was passed unconditionally to `getaddrinfo`. This specifies `AF_INET` or `AF_INET6` depending on the value of HostName.LookupOptions.family. `AF_UNSPEC` is still set by default (when family == null). --- lib/std/Io/Threaded.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 7a4e2640376345437afa5721b83f8ddb0d99453f..555ff219d308cba7647a791bf770b28b6895c6d1 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -13923,9 +13923,14 @@ fn netLookupFallible( var port_buffer: [8]u8 = undefined; const port_c = std.fmt.bufPrintSentinel(&port_buffer, "{d}", .{options.port}, 0) catch unreachable; + const family: i32 = if (options.family) |f| switch (f) { + .ip4 => posix.AF.INET, + .ip6 => posix.AF.INET6, + } else posix.AF.UNSPEC; + const hints: posix.addrinfo = .{ .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true }, - .family = posix.AF.UNSPEC, + .family = family, .socktype = posix.SOCK.STREAM, .protocol = posix.IPPROTO.TCP, .canonname = null, -- 2.54.0

O@P!9Gk*IhH8i03!*a+wkO!% zc`X3`E!%w-QeHO_5~R&tl&~xf16Vz+VW8&By7w23QLRwoo8wTUs}QRZd*N1e~O&B%jzWNj67vC0;!fj=aFT3dq+u^b;K%~8&Awz~C ztehZ&8+*Jw)rzc zA(?Njoz&-f;)vrUfu_p5n&gdO2|;wzw)H&Fw5TN<_a-$fDd|SVgRvD|EW%&`18g%( zLX3)T)72X_Gs8__VM~w-t`7NdY#}l`pmoI@p`E~hRqk;}>&%YW48BbX@$rkJ-Z5g3 zDC?(bn7Xs5C}ZfKh)UC!JM`UzB!uH2g{#0uqf{Z5%&BZQV7HEfhcO5)Sa+tS(mSnv zci2dPOXmrq3uozl-rNiuKe=BN;X@)T1_5PxOHI05rf103o`Gz-MU zClG+CfH!2Y6@zo1hJ0P6Bil+@&cAGcxEb!^3JMWpP&_eA*1aFOR2?6V3`TT*JI43r z^0YI03}EIr^i%D>$Bigro*-gMd!uRDc*kQA3`XM6b^>|N*lbk8?Vj_{IEWcjmZ!jZ_sga? zxC^Cg#u-;spv@sFhx6Dh;T&RhQQ?S^e6NX&5FxCAlE1=4ZA(aeeYzzFis>tBXu@kSVW^p zIc1YtZSkpl+6?|h12c%Ad2+N{WtlFcok)|Si*d&9i!H7wGD-kkOh-Zjd!P-o04-^) z{XLno)NKs7dc6%uD5e(3sS*i@*kgZi&p38iI*>jT-wNs#t~U!qtCgNFH}J0XeE$U9 zx6A1nvM!RXpFzjjz$BSz@(&+@^g!8S2f<9%3FyIU7F~%62v=E4?fOIEn%4!4$lGSU z5hmCV2j}D)Jl6?rKpI_w(^NG0_=K9O29IOas0Oby;uAghN@cd2PY`3_P)SB}MK?$$ zcE!q8w4qc&qBTB|NBuM&;+v;kj9`g0bx1CJ_<-bTJqZERdkGnIY4P5;h;g$mLyli^?pWvt?O+!>}%7=ZZGo9*{Xd}gjE z2NitwHpaejjE)#!Y# zV%9;sNYlqtNA@(LiUTts&9n2>EY>1Yv{(mX!9js-Q4owZAL=?7n}H(wvjetAuQNk1 zW^L4fYZ!s7h8|cLG9X%_8$e+oO)6a=JKn1o9Rp`PJz5OZJf?TiCpQ55P}=11fWRJt zkf_t%j64o&eL}J!QKYLY2|yc%v89s4h*rm0_J|}nrZC{GnvMniR;wJ=0G%96Tlr(9 z+5$D9QrhYD2#z)1RY(`0gsFbMN&lwa>3T`7qI;g`Ml2`A=VXs% z5862Z!c-m*1dTF-nysW1iWgm#KoLA?!1Pi3vkve#jjJ+8S^;rc|0?8!7lXwRXYFwF zZn0vd)Y#+F2Ba;_=~&&^S#pO-H< z;(nEapb<+z0{>Ia9JS}a%llvr_IKA|tn=tzv z?N6K|N3aniwyb9i@C(3vnV8o3Ao7WHPGvm?Rsu%LkGF@kibWXfjziWH=XDokue^$1 z1u&b|NS%-jB}_Snwxzod86THo1xhrK9N z-DAnxDOlsqS>5ZNbNTN(P5^r%v&`5DFkq3$feLF`C*)w1@;>j~r zk0!Z^NphuJjr|Lnate@FVwI@p@~>Kx>X=~fDNe48ULFFuJ>t}MXj$knV(%-XXHlN9 zm33*h2T{8T^g>}<@E|U?*U3}?lOBA}CXwf9ySbLi`pJigUxpC8doWly!d3xREk__& zdyAnUh^UyZpz}gL#dCyGGZ+2{+1g|>*uFO88u>=i1Ac?2`)azxW4`isV98n7uvE5ftn`_E`L|e*ffQr>>pcHAn#$&vmT4Nw~x=Nay=4zANM(Al675F}B0 zvFaaCJ!SO@6RXhM8|Q|4T~dLvIxdcucNR2AVc7h=UyFG*_MH-~;EaS!z1z^sI4W(?MGKcNov!+De!v9}J zafgSaqr-g2WC~HK^9<1tiPSkR{xd5xLU%d@oqO|hFlr7VjKV~y@!o6QOp#&#E^$=Uexz{eI zlLJzXJVk@kVc)%m*YYL^``zif41drrcP?#=abDZF76lg=-x7082Wj<*P*qA*{>GVP zOTE~B6*P_Y8dvafP_4qAM9XT-Gi@%9(b>Y$muk0_w8p9_DJSv+U*4>om1~_oR4*vP zjp_A(pAx)F4w6TM`g}%;nS%0+a51fL{8)@$2V?~56N;f(!;lk~z+}zy61d{3 zSE*dh!9Q{tEK|5##0&ZAZ`sTSxd+x|x7`z_yrxl*s_NQgIX$+c>#(>Oeq$1=0Tz6! z;DKS7bCrtq#egJ*ut!Vt?qz5F_u(Ho%C<_J#IWZOoQb3ShAA zZPB14C*oP}>Mu0%K3HV^x0u z#F(mK9~Pnz+~sOUc_Av}-y|nacxYF^F>f}`!3{9Oc!}l+P;cgj()e#|M_M7IM(l!9 zAhpd<#T*fv~NN2n;N@c*UH~_0VQzxp}j~GO4Hs%B?nBM9(34Uf?k7| z8^5=jK~mFU4m9{Z7;124*;~t)N!@5&_iEO0f!yG1pcFhK!d;N2Kx4DE`}zWb>o~T% zF-guFDNQDr%2={)0Tz9Lxe?LE=EUZ8um5s=BO{y3o2<{8pssn(@CRhSRW!aS*)0Q? zS2+qEh`|vec>D(^s&ZF^@XTJntRj~ljR}Rx4=LPCO6#4sh%ahS_rKQ#Q1US}Ou3n6HQ5QO~H6LBKw%h(>|uAZZ+w7JyKT9 zQq)BOEH|HwMx?0l2CM6-W|T6v|Bky|+dn~LB|jK&_xh{wn3W<3YjTG1-;K9^BCj72 zyBTBrnHp?qEwaCVmnz)DJx=G_uPeko*b^ih6EQ7(nozADg!82`qyp3vP1G+0l;Z*s5!(Y;+bAx+vLX9F-!wXZ>7Q#GBL@+x5 zurUt<%@*g$f?Gv4JI-MSr3x$omfV6^> zNqtS`SXu+pI54g3E(;pENwR{_Q-AmxI8}$6b&q3|FyJ5+k;~gJ(e(HdO^+|-q_RaC7&iY+4KWD^~wa*F{&)uGyl$_Hyk?NDI{28 zWSU2_)>=w4&HU)w;L5L})hRpuNA&-(Z7q1`oMP`b_GDXYN_Bg8UykKCQ3Xb!}eQ`X9o$_S)ib(#TsdwXHvBvDXXG zr)e*632XS*pP(-D3G+E1viPgyb4X{-Iw*UoDf3yHiMxMG0a)M-Y5a=BETGcmbsw&R zac(C0RBCI0X5sT{3{!t3=v2YaU3-4}+Qq|bKVN_F_PTvdz4L2iFF0mTpvc_|;)MqBV}914%!iK=%&?p0~> z73?Q>s&mYJl(1aq(1^=`u|TU)e}H(FeVm9qakr!Fe0}i${@`ZoM>xl=zhM~L!kNGT zLOBTQ7pi|W?g-%Hp9pvf=+Zr(lE@tX;P&Cg!^5Ai9~{b|Jd_(alpFZ&i{avE-kBXc z4y^$Yd5o!aE}1JNlrU|+gvzaV2sN)IbpGU-6wuTD8ygjdu~SSfvFc^<2=zOnWrnfi zk>W)j8yFCBuhNsWPzABFwvwIQ@1$UbM}9W$es+pT-Qk$gHwOyh<%JK`SZcpA)IIPL zlK~iL_FZ31AA#R-H9^OZ(M5$!*iY&4RJHSNeRzF=Rx6NMhZQ%>!&*G25|#ixjIG8w zVP9?ff|s{I^U)XwfQ#6KAcZhvc!p7Dn4UEhTeOCj1BAE$CNPY6&KXAo4%vZmbPWXv zkJ?Dkkt0AsS?oqpozvn$8taii4xXhld*$M>!h?DT`W%GS!17@M2UQLKWih zR~Lx0u57@#%nu+hW5;~tQ#0&dSe$6ITR@}+tgAvM=7(q_L=_l;s>3F<`%QPmd=I+1g_abPiVcZHHp zGZ`Us1>LeHFvsbf{r?3EqEL>%*C+?looLDnZxv0^P6y-%hm>)B|JVL!g0@eUCU#@_ zkQ0|AzCMBG<`QRYfxv+Hv9)orL3|Grw0ZmSfr`^d#F92w>XnTQfSsq0Kp}yW$UL2m zkl7uHOftUtHI)d~_r z=9IFjb%oppHlVXQLk7u6h7jusUY=q^d%ZUPDtien!BmxfRzoGq zBHyIw=MJcgG=+MOtb1(58a`c*B)GQG?0_x?)*sH;%4%(b1}V_vp(@fu@F`U8TL)re z4?uv+u$6Zg$oE0J6ETkc=ePGS9`3WGDDLIKz9fm|F6M#alfcnrMJGm7rpTGkTSJh= z$%Z+mVsnT&5>pzB;!6i0;sPGzd-K}YsLgH zYRDknitXj=vmIZxfnohsnFR*9f!jBWlYC08iXd#o`2n_uJsMzjlf0Jie*3|#Ah#aJ zT}`I*zL}EzJlk+5TJuT!ZnAd*Y+DYwsW30gm6)a+&!u*&aBN2&$0J?`f&7hxb5!Sy zfEIehaJ$Jk9B@HGo(W~=LYX22Nks(;8-Cnb#Ks{)oU<&X-C&>^w-%TKf)LShO983e zqpdMcVV2HRET&x{v?n(GP36Krlw24aeAFFr2p#M}Irl7sc(lc6GRi{?5CpgrbTeSv zU_PSS;z-WBBzjoqDdfG{Js*|#Ed+L%w9wLC|0n2}S!YH*Khh222a{Um$r(1*Y;oM7 zNpzzfZ$5$8xA-xQ8SY_NS*q>~FDF$hxY7Hwd#3U0GdT5-{^j6=liXp!R z9chdl*OSMNT_Cv-g1nxPA!q}f0XdeUwX@GzW3r0k6}AzOrfypYq6w4)pd#8NVv!#U z1B8lGKWn1SAVA$;lYvrA@Yw$-G_mcmV7_38TjBDcKLBQkR&wf(PLOpw?;ZE!){zzb zeC?_-^0ODJbc_6$P^_(|p#T&Xq8p4B#$Z8|;TXn79!^9})maZuZZ3|2PoqdsY{$zO zT&`(P&0c7L5a4Vo`f*bzGU<)q9~$wEi%Q$Fbzg>B>>%fwkHNhluu>bW!V#_`#1`WpeKq>ROV9wel6tNJjpY z!R#i2csb}D$9EZ;pd}~Lk#r*l0`ckk$EcFQ6OUXr(;Tw)6%GfDS#*N|SrjEmq6^3w zwQeFIt{2W>b$c3xMdUAA$%|LeFo6%~VVHczLgKM$HPdkcLH8XZB(}&fHg>ur<`NEeJNk(&-nq&vth?$vq-bnx?EOTDa(^NA6Z1SC+fW0?mCk+v&l3O z=scEa;$29tZo}s|%rKTsqNbaOu6UH!mj(+i!GY-p6*I#+Hz9tO>@&nnD29M3UX>h& z(9g_-&>4I5-3!ZcsOzqL`a&6zTJ{vvreGGYf+2CK_2!C@qSrR)E z_OG?_-VPoF_m!EH;s?#`jT`o@&^S;(g&@t|3ceZhzJXd0XRe+fq5Tm z_xv=9+sDf@Mb|0een^OQ@G}!Py!A`zI*iSx%c(d1uX_hNcLJv_(php(_Fe-H4;>%m z5$tn>ym0doV71<20=U5wRb#yjsU&bIV=a``tge$~g?N&hh7PHzFislDDMnn6Mv4WY z5)7CzMCz5&D4Q1|Sha&J+(b+{3QiDkXDB%IWl%E!|M6=G)g`RaiJ&5Q{^}|DL|{|3 zgh!=V*_e02z@~M%{u-D#QjpV3KeZnCC7BU@yDh&|=x)@S@z(M5_iw^$R)hdd?W zQiv2zd$CUCXtF|feS$@KYu6x+!4` z(N}CXG#i|Bp(;p4``m2>@Jmbt2Wzh+$2xO#t;AeY(i1|EuxgZCdFR#v8Se+O8V3?| z9Z37yfkbLI-+G46UM|n${R}46myCYK5ptGS>#BZ*@~U_2@DKPlzsD8kMo~SZ+=VwY zf}SR>=4qcnplgyov%(PagHS61tgWdgt#=D|_%7}OA{qQryhDDkC{nS1z$@fBaJLU` z$rTRN72MUn_AXmCmT_3An}T{kIOxeZn}NNVAxj^?b(gkm!N!1E-{}^>CLe?b1_3Hk zh_R;Gj5E|70%YSynyFj|1MjGsR}$zczw$Cp5^|%Lf#vXp*)e5c%Wre?5gtn+jJIbZ?6d)kd>oO zJ9f0}Lt?6}-h#NdiLHJ=Uyto@1~oC&C7bV=kh`XULxDtr%V6(#76Jgyoi56?TYXNQ zqIFncq3s)++!6vk+F#SPUuuEHij3_zfx%W4#tf9O9hISyWMQ`|mW@QG6i$j5uAm zxJR;hRgtz#X~jFd{fQ33zt(~@`uo^ctxvLj_39_YUT)z}eEAB$+-dzjzdTSN%+1y{ z{!JqHUGYA$z8lrLpo%^j!Fj-0;&2&Tg+->mt;U2Rz!Xqza2DNsu3|gny%GQwC>UV> zEYzzQ>shwL|5QgfSmCqoK<*7=j=qf!N~lIeJ;~-$`j9}37G5R~fyA5q1lJ~ftv z)kd&G$LSm%Sz$d|N;W(CtqLVsyRo%UQq0>kSh+n!Tv@KkpyoeEu3CQhjeKZLjETq9 zdPMp2mC9Oz4THf>{S>0NX8dVY1cqxe5TG1m?4$H>tzwIoVt<#x`1^a<6EGizBnQwOAM^61f)7Ge(%_b(Zyi2}hOCdJf! zfvTeA-$o;ov36NSz>vnY+0!KfG~uHUKqdA@CD(GmF5-klK|XE*vbC0_0L>R~%kvWF zldA&`w1Po4Y9JEcaE;XURH zk<3)|lmYRC)R`xX>~%EJF2FHGC6wwYQ?QYG=tT7n01T)ZZHt2w9Uglos6R)7`YT}p zvj;gx;hQ22y|LXx7UE23^(d!13s=~H{i3$D!WaKNg$`AcExEHSItTSS z1~Up?bWUDyWDG*q%h;*Day8mIsfv_&R?0IZQ|S*|9 zjE&2!A3-x+2#Jg=dVI22Q1CQf8cRZyEUER1Q4p7@1~DCqY~$3tc=sGr`Mm8ZDzTlp z&BfVV@M4&aqlf|;{ixNRQnf57EMU7E!M5Q5tbNoSV|PB2mKpWzV$2RSlM1^4#~8=I ziK)&B>s*)l7^Vkt260oaKfa%_g}qfzWFVCj-2UGllD$`G8Su`o3YKKCsCVOb9^X{2AeA`+5*D25Qa7v8C%2)*?pA>F+%JP_f- z`6AWxl*1ap{5^t}5?)=TjU3Kbpk7TMCmqxQEaH_9&?kfNdQ1owj&OI-77&gB0{5(( zBMt126kr^ks<~Z@J2>)aA>9FzonQ&Ia+~bf^_}nhDY0c#U2QKKVv`u5UID-o;zK`2 z0Z>%)_@Y-_gL|VK+_Sftzl|NBkbR|HG}@ttA*!ZWAdO&;+^LNBwC}=avnx)o70d-- zG}5zYx~jKjz`SmUqi(QI=JSAteBKAl8poR8^*HUu0cW?5SZSM0U|vNJRmY(vJfY<4 zYG80^yQQ7(klYY(LBK=XJePrOJHQx=L0y4#fv)mFKQvzg3R-*IP>v^Gv5-VGtHgtc z0dKtv**IupAxLs8zW-4)o>7{mRPnT=9nZ$N8uj)8qe1v$X2{vF)5l2yzyjtBfiXr~ zKvC>9#H8$%_=^VRVNzh?&g~9-C0ry7`@J{Reb=>fXWcKl?Ww+qmSqk$rP2-w^Hp_L zG|MVfQ6@_&5fw0A^7LVtxMaU`)_3icf08gGA)&& zsu>#&p)!N+%%VVNNEl$)LK*3_lFcf8BsOxlz7Uy=C}R;0&?78CRl4xuWWIT2X8m&$ zY->XivW7a_+CkKapok-cnw&314q|dF8`Ld`-`vMSG>}L>e0s_9+ziuDh}58fD9G+~ zD(Y8WpfQq9nYZ9V1#W>E>guRIXSPH-9RuOVK{|C46aTZ_Mi0&yNUS=Qa6D>0` ztDCut;?SgIv|1a3E*c%PjCb;As}%0<(>MwSoTS)lu99>yr7%%-K^10dj|8h|Sz)SG zjJCi0xBdkVafzy*!Lz@P{oD<$Bs};Lv=wFx&yN7i#tbY*grxj`o-Pi%p zB4rbR(xr%eWrmQDh;Y+RT{Un7uWAM=zUjccR{FHJBz1faDRzClRPsy#bcO(m>TbCbYJHS~`l2^c_cI2gj~ zSks<;I0dGymTWxiGD0SQPgid_9k?xYrDGTuItv{<|91P<_pmR~;>Rz=8XS%$wFh@F zYXDb*0MyK$Ad7qQ1*`kO*s22p0%lgAghWUtawhX8(OTALi7Dscr5Cb%-EFB8y1Lzo z2i-{rDb5l)UnU`f5W)hs%wmWGgY_=jD0JPJ^7yM?u+Qce{$#rizo6ZQU-EVv{*CQ6 z;zFP^uqzaiz#us4fS>Zbk-HnyoU94*m4Y)_(@}l|bHx}%nhiaLKv1-TbX*Ap`M&BW z&&K>d$EF%AwoJ2sKy4s;=_n|(t%CWEq=O56_{uJRq7o2AM?@4N7vbhG#uxqu%gW_% zVIps~N6_AdJ;Ek0>=Ay!9^n_gN3b_UMU8dYDnhMlmd#(Zf9wpR2Zvzm9@4lg>DJpi zI4A8v!C-!_D(F6Z3yVs^`Ahz^9VRREB!q=YM&Y|Nh2+g8RkxI8p7RgnK;Xx0$*m!p z!%vD`V3K zu8T;(bzy#A7mZ$C4>TZ)Rim_cM!A?f!U=oF~FK5&#dER!(m4;sLzFf0@- zj#^E*)#iE%GS$HPK<|wtpQi=k$p1J1Y+}m`Y)Lu1^+M`Qk?ybCSJOFQF!-IkHBGI zoKvhyDLikltkH!!knV$w8g9t`dQnZ>$&pN2Y}5`EL+-<6z+?g2AO1r5r(gfmO-l*MQ<3J&>7UGB2MqjNGQG z2SO@OAj}6wt}AI00Q;_Ec}T^qhRE7{-F6s-4Iv!x5bjf8w5ME!du1! zj@pp1u~`BHTaQq0S=8mrEZ$-J_n<*!yq=aSl5ogXDpKm*5GtBZAu*p>{EPx1K4tUV zJj6+vpo}O$0K51p8%}JMVdFWr&QNw^5&&!qXu>J0*4LvkHj3)IH*i2?Y_N;j5_X-u z$h;5$tQI^13X+x5wTzKn8orPj161B{tS&pf=0~*_LFg?aNnJ`;@WBE*qs}~*qd!MS zR7`PNYYx(MQgg5zP9*Si%m#jL-8^GLCY+8i?KayzoR+E7KJ6cbrw$x>--8V0quRGI zRv8-tldbLVS3~7%1)d}vD$Ey+yc$QQIb$b7%)6lAb(u8m#R7~ARFF=giVCs1mC$mV z7*i}NyJM7ZEVi(rRf8j1>ONYv(N{Ph3Ym5Wh>s$z2o;y&!)>eW8*laYkFvm(K<|&- zNbS~-ki`J#<(DGR%Ud~CB<_YXgc6VqhI34Sx5Bbyl|^MF?dW$!9eYf8Ko8lYnYM+!u2A^-#9 z3A=47YU?V=rsJG76k%(C*>2^gA<>5B(214_nx+4sR*pH_l`^ara@OWVtDH<}S12-h zefo_aKDd;s+J;a$q{#NMrZ(ZpTF{Tn3Md~-0R?}ufWj{*pzupxWaHmtauPBE{Xu2^ zN(zFOk)UuNYyp0$@J)kk7kI&$W7MHj0 zo70s&Qx96WY@u^ZW=Ua0qQZ)x&gv^FIH~7FJhkGtk!rrv`oi3Od7kQ;VqLqn06y<< z*{vyf@Qc8=sySNlBsA)Jpit)PeW0R882v7BRW`?wp3wJfsv+6PV`tI2@jMFIp<*#T zU-tk_vf9o9@d5*SDeiry}ga|>H!*@tY%0V(Rz>n47?ufiy*9z&;$r{>I#MDZNj&5YbOqfJ<&+oT5eE>1s;&|R4zJ>=m$~}cDp^Ri z3SHy2bE-axn-?Y{jI>9_U@G7RI}Wp?Bx`Z4rZ}2SSlTzz7N!e;ukje@s8=Qd5l!1VEVB>j0) ze0XHuaemi4Q(c6j@)I;YjN(-6SF`)p4ToeF3NubXcUma`$W&gcic>7e$Vf_P+>J1! z4v#y6j20?4k#}MNdcyK$lqOAT&UJl)tDKN%xu`NhE{4gcMT-b?6ij73#EDMuUc@bK-^m@yARtGn`l9?*hrVXY7W+4JS81 zz7fw#@TnZWL9bJxUxTlZEKq37`S!pof?JJE@AoFyHd|aSpZy7d3m_8|xt&d7(_8BB zEqprAfXFw3Sp;exfoDNVs+(8m(ya3z#Zr>k&a|zUI_c( z-OZqqVA$G+VX&PCI{JkRpCD@n%M;;H&d zGE1t)d5F%4m(x#ec^ftT^grVK)UmMFIBq33b1auSP2O8C);xx)poW}42d*R*voWE;V3BmXO=-`*YO zs!c`1c+#XY)51#Y&*_&U-4b&b$mz4$c#&e3Xg=!5e(QDE)nEXTnA~pIzh0#K)LhU&-EQr*&{X$BLPGWPK7NK?XoSMPqT2EFKRzDIs-Iy3J*J0(b#B znVf2!>NC}(e^?=hxsTi~Q$h8o!9Z=1L9dIOD48=DVg45W0~rSPSPy8i%--e#p#hZ& z)Bz($MbDyzKEY_%s3>joJamGx! z&Z;OCWta@AEf+d6u%?dXt%86^?_#l7*w0UlJr2k~=P;NnV0YpdeF|V~sgX^HjqfIu zIjiP_x7Tf;_fVI(aR?Wik2$@4C@%6)T;!p2=zsTxgv!EP%I#W%BRo$z&jqp~mN^Uo zFtG;#-7h=yWps8m1Gxer!mM+uo9Z^7LZla=n$r7KF0Bb+7rv81;S2DEZEGL$c-bjJ zz@}bUR?0$Qb{BP76PPl{{vFCIWDhD*{IWH(CsiHyksAfJ3z|4gnXP^L_P)z<{12Fn z@;#Wqt!5p>HdyWct|WEfd(mn|P^t^XQmfg@OI{L2Ko5d&YI%q%LXqn-HbR5L+~anS zHs?~*t@CwetI9UT!-HHr?kpb55RWfOb+}Lo0i7{Cvo_b32U~yhi#+N%>1@mY{t!X` z=Eo9V+_!%Z>}^&`M$Y#n<(BXz-iV=2?p*s6bNLGV(tuzQe)-WC9kQ*ZhTOtU{)4^Zr;nBuW9VI)^)>KY>Vk?-b<0W zN=IRygJ0dhjhnF|R*Rj;Bk#UCwPWSl4bYL^5Yr3{8Xkexjfq z(9F`|N$N`F@(Q`?0;q*f1lgOd&}Ytr|8qcV*4gh(XV5S{f@XUJzjX&P*?isI?S7gF z1C90S?qC3^fV4G*Ln{9|}(;x_e52i7K;BW+3#>|i)%?NXU{Wqenz`dWas@pRQ!X9q zW%)s31`f;J@db8u{j2p(`yN)Rx_Fe-dN*9XsA0c-AKdCt;tXHL49H8vpUrA|E+orM z5XFn6sw(|~BeeIn)9+PzJ8JlP`fYZ6UB$2LuH*;0EBO(3SMpEnu0(KnZ#E1&j?HIp zi;gzow)c0dudS%Q-HD`mv|TLAiO^Kd4ghlj1?Exp+V}X!E$mJr+#0a_C>gL2{s*F5 zKSpP;*fIqh^7QZZ?}mdYC!8A;EHHv_(0OCnLKWYJBIFh_fHaw;U*3yoLx8mr0AF4k zg9gKCYE2lZz>e~MzmX^&7BKc`$CxCFVnq(DSac%O9j;pjA>XOYjRp^+H1@3CX8JVI)JT zh;{;96yPK;eu&e4J2SV4;0DzoNq`OLF)3keHf`5!@%CpOwDN#0 zpB@)nAZWI>MZ;E$?2RS}XHeZ(XJvfCSM38?)dxNRMfczoZ@dJW7=&EgY{ZX)c<;zD z*`k%JFUY=SWpCa~+>t*iE{440;;xIhqsi<(;vn0CA>vncXann%tO`a_?QNWKD%D$8HZ*(R zKz(*YqL~d+m^K9E*pT|{h6FYnqM*M0bznA;jGpsg^Rvq^To4>EEZYej1JT?Oerq;CjC#m z9blE6A<(no3&B2g0A8Q?#Ol^+ShNB*l`KV^9m1v+e=jJcj#^BQo4gb{VJbPgWokYj z0NX^PGGSnVn=WS~6=2xEvNj{G+rij%2S$}{vc znnqZ!zqq0|74PrGbpY9CtKZ2u9)=BR>I~I$fDYgoys;7(23?3=3LCVKl0MMPH8_;6ipbI8xC!PFZlK|^(c2visdXAn0`!rx zULIf&b`E(~CPM=67rs}Koxn|vdKgS~!mctl771Eoy+5>pbmFI?9j)^>oxdZ)mqlzl zU{>Q)*M>_L>}qsGB^Q0s8InDSU2B*Q;Y?zhU$04u_wqZ! zg2sy$B9-WG$;j$i{oV}PpR#^p-5CEyuF7&8)+iDcIY^fj9s2%2wi1005Cb4 zNl$;^W7D2D#$%Nj@TyaGTB*iSoZF&3NS#uu+c>=tnmFhU9J?f9x-6zj$5fIrhB^+C z7w3l;XYBqO^zZ7dYIkQZ&Y_ak7VmEmyMV`qZIy{z*w_iP7dJ7jcc?gnq^qIo5dYI6 zd(zOhq|;5W$H%<}HFD7YSAZZzIsc>CG_;d`m4;F5J<#MN!pE%cCEjI+O56bGoP{co zfTv+(IGGY)WNY;SBIwO`MhUymX}l#=pr_yo&?~w-d6h^leg-E2HJ(w=pRj;p9R5Aq zR6}G&X^4<#d@1%p?#s$L4-&aV05xaSLH9#trM|@s@^Em#_#&crdIy~@yVJd?oWY6e z7fF$DF!69@=7C%MQ2h(g8+IgTZK*9fVv zCxHUm=uU?bZwuU^P`tk`S*FOKMxk?x?wmTsu|X#NU>osX+W7 z^j$9%Q@i0g<+~V4A&?P+dnB^XX;eBw`WVHZG1w#efFZ|})2v~|h6rc?=7RN+@CHpt zh6R#w$UhFdK>*)!a-)zA>9JT5saV2PH4YBO?c>#5D#xZ2mTD#_Kndy&FnxaU=#aDY z!lDRluNE4UdhHU9XLlm%?SXg1gXC0$7(wTwh)UTm+4JS@?3~7)twin=1>qcNVKGk= zFKuWEAPHUzu!3+XgOwXL@rG>@BW_~qtNBP<@;1=6=&WBJ97UR!oihqI0e9mEQ#uhJ zb`D%mqd7(Y{zRii{ z;zBDpsYb4YqzA`W%>Sa<8%$@dQ62M!4SIvO?v)&4;#bxh!bmkh?Sy=;4n5MNQTgtE zpIkc;^{l9Ngu&<*3+TA`x)IP7JJ>dVZ(to}Ms5-?dR&=xecQ&4FE3u>FCnQx&EgR~QQsB1+~EALJQ(7aAPm){#j z*%%dD$D?^?uX90k@PeC|t>#(~S3Potj>Dfq*#QOohgY|0jrNjC4!EcOEjOGl;%Eie zSuvzCs%+Bx4p5695L{3JivYSD%QAtTD}~S3+L*$Q5pwswPgtRAlX$EGMi8##w2#3; z;gwljscluyq7VRhXA3)K>2%0ABZ>4tDuN*w++guIZZ^p1^+Z)*{Y(?wh0NU!JbKh# zZXPpZ^Rx!GY~wJMFAITkx7Z;Ng{6~~fos|Pw|kps`dUXd+W&6peXRz=9b94PTmwlo$N_)ra%+o z&noBh&n*_BClyJ^Io6Z+04yvHnwA1BnaQ4`{EB8oIyDnNG#&A5F^0V#S#O&rndl)Z&B|7V{O15nPTi|ru=?EI>H>Rf zgoZaMS@>pL2%ix}_D5(h2sREPrRMC>BEd~c5YG+?q1p1vB&{p43;@ab!t*_eWcF*4 z=`eGCc(q1Wcugpql0+NIK$LP@=0Jq+f7tCHv4>+v*pO_NEb!iEEY@*xETjDr`Y%Qc z^k;+c?nvzU2rhgi$tepMQW01|jvNW|``92^dGx)IOvnJqK9L!XZ$7fGlq3p+FQnq~ z2pdscBPS@*WF2nk4shYsQ78^cwB=mkDGtynEMXN(TW z9|;f0%=8za_M1sGWXHcSbB6ZVb zv|_mtR+OM7jSX}R+%9mh!U#}}D8}%X6{jTv!MD|$>iqD8ZbDojPlrRD9Ym#TEJx1~ z(3I&+2%90KgJ;{j*sK2L#eVe*7h*3f7l?Sicp*H@r}42@y^3G)@fm(xul^c8?o^-Q z$9%WCC7;`in-?_dnP_yqUY5pw)KiqMZxr#atU@wW;A{4Br+8r)WC2^8zw6OegdTe- zLW4X!Z6bz)71mV4>sA3!<3`7)^*Xo%c$fc9UL|>aAcemdRoj&@ca7!tM!Rv)WepUd ziP8xckA{$bY&7pi8Y}@8M@_&0+|h}fIQfm&K*u7xghJ0J!-bAZ?ZGYr5!s3Rb0CJ; z3@8o^A+#F`Yo1;*g?E)=xuj9yT~KjoZ(sFN!9%4AJ2G!0iUo=sJLzDxQ#)Q=WI|PR1C;&`Us$in8-EAC)dkqRBWM72f&H3Pn`;fsDmluiu>iK$Ws{k|vIe>7euk;#~uQDWyIu3o`>! zB_*aqhlXR)A^E;h|7=*mAxk~?#&safNLjqVT}bjMxh9mg(QqaYMM4s7%{S2vF2p0_ ziNbHkyciu^g3yHqCow_Jqth9DhEg~z?BGI^I3La{{1VC1I00BTE-)ocs6+>@TB|3K zS_%M&b%-!{WD9XktV6W7CBAe^I`>tQXiI$V&VvUuhPa$_uv|fS6Te9%qNvS{qYVQj zuEY@$eZH6k5n-z{^NbD%g=H1`dNY1^A~?JpnYJ?$3FK4Y>OUAJfKK@~nLHABxRl$> zsNciiehh9Qg~!lR=4uJ~aCyA`Y{H zbSyn-txO^(wvF+439fmJJPai=8D)V_2vK_gO&x+#`T;9iWn?Cui^bQCf?&+WLN!2R{9Mq99lC zE5Q(c01V-W%~KZVDi7D5LPk9_5T`hp=tz3HQcy!Mq1AuCDBqAIPybfR&dPta+ zC{^~h@1g0aQJHhhuuh&IF_T$WoKWe9klUW0%V@R01#AURyCpRf12l4QBhg(3D!Y?E z`tKV}MY4#Gsyn`#6=z`rgj_4qZlMoD3mGFD!0B~v6csY%y!wwD21>l-htE3G@cA*E zt`^B^jSc`BcA$vj+_WFi7xjvpl-nWru&LMCr$tN#YL6^BO8wEf#R8SbHYe9Q7_Idr zw7rRWkxN7Z0ihxLW0a)5vI}h7w0viQdxui6^k9db0A)f0=W^@~`ev~m5YkMhh!q;+ zyQ%V@Pe=kr`29vbO4=!0R`2#lCep6Hz7jwblw%p>_4{6-yFhx%FGI!&)5zRekHr~F zB}YqIud;@iME=IhaL4VI|-+fFd+n&Z}Tcw@L9Lj!I+Pd`?F{k+g3L?Lrb4j^UEQ zgjz+UhlxT$D)hVj=$nld{DAR*M!;{MgG-Pg8u|~FN462*lb7ftu+(ev$j%6lG7(fK zQI)N3BFgoWGlG~=REDBJGS7H4h>$=N6&@vsc!9Wda&X6n)nmQBE5nYbh4n9(? z!m}q+h`&+STm1=^X}&F`hrR8y{cW;aqyXWxM(%B2{We!~`!oD7eUjUfmhXP!+t^v% z185X+lp9V|eavQW=Pi5NXh9ZD$n5iYN_}>|x!3`UHhE`ERY1y4r!*s>NZmT<)gy0x z93|q?gsTpQ!a}oNXr?Xvl&;H9fk`dHqS7APv}Klxw2G};)Ua$;gSr2;#baS_l;U$q z%)uTDdcoLR8;_{*iD%rvW`1}zQ`vL(>klmKzBY$IDDeDqU_Kyn8;#C5?lr&Y zyRF}-L7#shKy?Cg^*)dgxG>&5&0Z}~K#uh;V?CXVCNturOb7;&0ISmpEeH|SNKpDE z^8Ut>7hdCj`Td|*n~dbz99m9#U8MNrZs(^yU~}p|4ypeMHS?n`JByCczQk(6XufgjO+-j~aiuq)BIEx3EIdV5~7IQR|8~W?B zw_zaGVU8FfP)4TL>GWpMX(*}DkKv$R5HVKZVM`*hSVEHTI2x2gw92~SF?qTs#<@WA zDLC62aAE|lpl2lx6E!^{0DQ$mPV#BXPqjX>PLR;3a0u2%t9!aBNE1c2ml>(n&YpdFcUy0uEYVdlC)+ zMb^oSY7P4hNP#yY#fk??Y(Jk<3*xOgThaPRG@O~DBS3&Fo-_{KRINaWZ0(uEQr4)6 z$|@KSDZ3`oWMtc%R)tt}QgMT{H7^2uiGbf2?e${T9hC`aB}pwXS)|RUkrYV)Aml57 zDGxn)3P|~yTbldHDvMI!{Y6~sthh+bB-SxOlqiq{)e-)Q0dt~1LESpZS#m(&&wj8ooxR zJD5P*H1NA&FEMd56X0M40B!ReZA*^$57v};7=1UUEH5Q)34ZclE}zELwFa7lGNR;i z2AlTpBC;TTM=_Q>l3&tnx)#+?be78r?Rg15V{vF4gXFsTAA@l}d?F~}5_0EF0Q*4) z=DB&)?X>{*Ctj=n?MZZr7Gu+2Ou{QXYX_3AB^X%CJkxSI0{eJnkNaPGzB0eQsC-Al z<)kWHj?{^06trJ}xQ{&@6n1k7A+Yt5zI9LA9B!33^Y3DU5;G)=!ql2)R*Bp4KEt*&l=t*To*1P1@th zQ8*_AucnNItZ|?HDe5s2Ei_0RiQZ+hZ%~hGj!zX2_X!o{%Bx{^#>XJwH-PS`At_Gv z0@9247lUqEupokdBBo$3=yJc19UQ$jhZL}(XOn4#03N%=Ei$4~!|wczs@z5i&)r1> zGD<~`iN|*Lo!roDcY9e$iamN6yf6-C<`jlWHKAF2+CLcf-2AG5 zL4bX9r(3Ytmo;%^4rK(ahz0kZw^Ib1#g1GqsQSPdh=wH7%5&SWp+n$7X_0>J*QI)7 zc-V5UL;2g3f=!Y1SEePZHA&niUK`A3zcC37(lBP~7GfTjw3r_OSzDtNDI*~r46e}A zAn!~(hIn>3_5#Z6CR(F5uu>1=dn<4d$iVB;*YW+D&| zmLh+R9((*gAwqXK3I1jaL8$}>hj*LdaO4kV74LIGhK043#_94WdSxLgmh5a>4kTz+q+B2_7qt`c?(h?;ycf! zbBb^Gm0&P)a54g?N%&Ct<1&dMq=1BBYg$=J_jmaD-tlA^ye3UuM-5CrfsurSHzt78 zXSS;LKJFM@l6uE=sT*+qbDgaf+{JlN8*4eBV+dG=ZLUeL5(Tc5h*`3M>F|7_y>yZ70`c(bgOYOv*!QWMF`g@B-=GV zz`!aDu3r@lcrSaTBN*sOjB0S;RgyFGP^^pq5m5sOy1L6m^>XmjAz*N{cDBdL@x=yx z^M7D=>@z>slWh7~RVD{SY}h?FwDD1g(nAy}SM-`kAfCEU&EuKfltDbWKsMn_%Tc+@rZ>WR%oM_1;#Cb7UHm zyWNpjq5<5x1Ti&1+cQy5mpx8dQHvbAx}wMsM%u-Jyd^8hR}#8h1~tKslZK-GW;Q(n zqoO{#>-1{*z=2E)VZea#WL6lZ>4f`p*lFohMB5Nn;LR!VAuJ9=KHlp#5x*R8ZmQn> z+JYMT7uwP0>^G0v)ZYk$#!05)6ckCl<7*)XL%YiBpKSVfFphzYp;sPri=m_tbaPUj zAr9$WrwFp3jP0!E7ciJx_0w*x5$p2lI8lk%L(~0 zVJ52-A?*iIv7-7ztx^BC|GXOw@qn*2ibx6Lr3065-3+q?(eo>vMvWKV$}K0+G)pE?trE0FhP`$gyEv=_-t58FcgH0qY>U#}Rt% z0jGoF1RaUJ^m^?K%4V5QZ9NH$B9yV4-A-5Mg0E^W$F9v^)WQMl4G&l)ggaq27y)q+ zn&LWzGnq<*W$T8=W=bIT_F*U#uxCBtmI^rgCbFsQG0)P685pXeqCLn}(dLV7kB`I0 zT3T^zM5Yi`2m6*zo}<;A*GOTBL6kl}lJ=`~0^{R1H0{WMPq1O|e}TTB)1Hku%1ET= zTpkkyI$r<8N0U&hY#B9J(-5|XQU$;!<598L{ZXrXTjHxZUTawEJL4BsJI4#LCSp_!fw(n^idMQH9>q@h>A0f^!BXVxzk7gR(?Crz zHlR7dk-@pkNtQW)_Z>j9Aap4Z4BiI%V4qZmC4eHkXC~+NVhpiBAj!7Yyw;vb%i9EKHCaDY7}=h-RwxdPi%twdzJ z_t?>WCgybS_pBT(o_)^RsMo*)n_J%v2E>>&{F+<#u6C}<4&1kHPi z2B`vXkU4qigi8Oy4wi!l(^OK|)*=(a+Cz-l0|P6jV3E}&b56a%T2V6NHf`4-+?SLy zn@#(p`zcyufpsP1%`Sd$UXsB-;w30yHe4y!BG%cS7YNLlUZX-TuGLdokQ#`eh}ppF zEI2#>mCF+3GNP;u2H-hOv$1H2Rg{f^4v8)q%yqLf)CMiyhr_^lDE8(iNdFhz!EoB` zoYu#E)G`S%C+$;~1&~scv2hm&S7aoN6ARk6fv82;`oH}6mniU_X>|{l*#Cr>Bd&sn z@aWyc@f1UP9K+$gDc$78$8f^=&8GL00E+jQFU~ou655UI!-D6TAUy#SgU{nb!HC=J zj1m~OZ}aZSn7>8--iDZH0vLx%f!(Ukrqay%^piWJ9Vr zP>;zjqLs+BX?4tm1usgLQ02CcLATxL#U~7l>)WeiB`nygx-|h%?B1`L5d7NWBM`>= zPW0m<@mdUZ_IR~g+4}MPXLxqdU*mzyDj>@=5+P7kR931|tWcM&!m=b(V7nwOQh|Mo zxFMzPiiZF^ppodwn zd3SWu3g^1Lc#~N|l(@Y4@aFu7+OM8*Jj)zxB0bd8Vf_f23E&`MM6jCufA6wy*3gAd zUAjdPOiGX&ms(WB)e~XK#6=m+>k#dx5+$Uxmj&F=&RA)|`)H*|rDy&C4KGMB0YtdY z@h$SSq;ae<54Mkt1r^6}WD@z+E>QL5#hZ2)$_7}|0B5^JR~tF&=LKDWOF#?>`3XRN zYlAOOM>}dv!jV>cmt{|fj@_42VRBIcRO~Q16cP)=!(+4>*>|MdU{#w%!fG!bj4_Zk zy!MZ;hYv*%IJ3I?@aWgPLjb-k!_ufSjod=GGpV8 z#`DjG=7bYWJL|)NdYCu1o%eAQbfZ`qEzVdde(!AqLEvdCmA7N`;cdbWI+p4)_&vb~ ze#GDd|3vV?P`I$%!ag<63PHN4W8WUgxwr*R7tMr}l(|g+MXxpgunUQdU_v%7h^fiu zo7tA&0x~jsz1>nhZ?5h8yVciLxDIC;(8QFATtk=#BM`p9CFbs z;xLsJrXVeXTZbWb*SY|pVnuhv&GKF4Y2Y%|F+7%3$b_Ac2dQ2f4#X4YM^y}+4kSh` zT$Tg+JbjlS0e)budG?BW6Z)mHoCE0B`g^P=nex=vG4gfD}$Nb ztCa1=7|?_Jb@of4Jw9k3Mr|GFoN9)iTV>QaES>`FIPgb7rE#9D$g4&6L%|ypUOcwJ zuZp+}JVbCveN{By@)B3IF;ejOis@G-YF#2a% zul@PQuWT-Uf?K}dLAAo$XKI}TxP*71gKp=@2wS7IE~m0Jff){!IA#865PhG6Z7XFf zph9#iJWn>07$yjpsbT!n6&YAkY8S6uASn!=Q%(59p7z-~jFp+TK*M#`KS24{rCY)k z7iV{o_mV3fK>W)zE-ZAz*cwpBZja1lVkFPe+KS!Ezp|W%j#WYY6v6At%9dqaZ_613 z*)wO#H;l$w>GBP3Gc2x{v7r-af{6*h;_QJy|6+gSaH9YG(k)ay=h@s@yfI5$?W1&_ ztI113l#mhvD;pmQgl7=qqycP@!~5@deh928ylU2NDYUS}6C0YaAJ29(31@@xdvG9gf4ApJ~kv;f~n) z!nQ}Tvc#3mu+iy~Q^*#zkn|&Qp(fVWf_;w+*5@7c&d;&a4ZprD!>CFV;jLs?ymsTD zTgO{y_F%LZkD5dnS3|#ej8IC3b~&=YvD=2ykO0}PjEO)0)(I!#X4{GzOdu8)v@x;6 z{L44-)QP|g3D0Tft#(Xhjqph;bS6+sMgj$uLz+t`p4)y@aGoPJhQXfJ?3}2WZzNL0 zPA?u4vnru(fa0Gh-x5^C4W!Hum|Hr@f)pJ1#{!Km z)|IC+?I?UT)ga1l@GiU>xBAvl8!uhNyW#w=n!+1NM^OrVIEEG;);6?8i(SGppiIY% z9bb{V26s2XE-aADvqd1Y`dc@1H4-mW_fj+h&al5b#(hd%91oqQcKCaU{NHQUO?juqRMPlDP zngt8)Pfi-4@(RbD@_cNhdAO9c{|ei26dmVCDIr8Ov5`yJ38ZID!!^+(exfM=&o5xw zS%ZvY6SoGr3{LuQ<4|-GSi~S)S6-zOy<`$)I!8RMr?5E~Oh-&w86!B?D3D9ope!aS zxd9n4z--goowVUya9LTc^B5L8@^KZ#su2p(ofUYSV6pmWJ)?j>9|(i@}Kq zVN(X4uYF``yAZ?8(%F6SUnu`yo@BWEkn6s1wK{mg#M}c|VS& zbXnKaVPn$lb_3rGUvIcpw9PRrJUl*Ca5(KXq8!7AUx`~p6BZ6NjS{_7^&J-kMj32z z9(4wsbX$-(o*A@!@qQCk_%S?K;4;aeR@oI6{ZL%>=EgmK$@hf^P70^-?ysCN4|P^n~DlC|!g3S_;%= z<*ib3yFSUj=*JyP6wF8@PlqxC%ai40E^wleT^$G`-3+;Nybtg?26l~BXbmy4kJ>q< zVoBE)@579BN5{`GM`^afAwaLRyZJ8<%QVk({|!{{AwZLE`&rfSL%S{WOc0}J88Z)a zM%;lL)D#MIbIsnH`8FC*Hk(Xe1O5JNZmk!nU3}duT;- zH@a5)-6n3~2>D9;K9^D+=nYs(L#mH3?PhND6#>XpmEcuWPt>TIGNMMO+#s&zjBD)BlfTwO}e z*qYA5&d(6~jssuy;(R)u4Vr17yZ|SF)PgL7G+{@O8AMmj#pSXRq_$r=zn5=z;8zbC zGg}`8frgA4ckwQ;m@zG?hdorli>=&w2;z#;!zS%MRjUG7?;T+kIzwRaX2Q5tSiEt> zc*1-p3sfdUPdLzcP>42t+em=;wCD5>9OJl~b(u@PRUq2~*LoPP zSE7F1JVblMs6H53QU;0uOm^SHvwR{?CCh)2KZ_-}(#A=hQ zV<_N4J#RL&;JA`I=l^nHmQR9nJo@=W2abP45fDf9@3Lqar63V)mkKIW<#10Y^K1;5 zjHNP`@*T84w?h-Zq-_(6VPU{B?3;?PMuQ$MEa*+(+rRUl)}(}(24@b>*c{8D{+Qr# zEbqhq0xGv%-n=WZoXOMkWv87fyti(^WO&(Vy_hOy`|nEPCiEm(QSP)!16js233h_p zRB)|?Azn6;mb$?Myt3;Un-)r1VqeCd7ORxMZ4qr5svziE{NMb@tXhVI39{hR`gLS<4A7a!mw@w{Av< z4!x~xPrrt@axMbPD1yzKpmhDEsoWW7t0ULLEguXC1~kn)jU=6CeKh+5U8;h3%r)vLaB*`_Ky!^pJ7YR zup6y$i@;74axr8IgV7e}$g@D(Ts&ggb#~B#eh2!w1jfi!_NBGYGGLOIK%v?_0_cvl zks9DwG|BRzSUip%?6~g@#Yoj8d|;l#--@Vj|IoChVjNoBm&)^?;de%8nfo|IK)O6e zBqsV8yP93p!MJg(l9$CDa>PM%VdKL7LAPExO6JH#$uwo6yOOAfwNNellnQFG@CCvT zlC8ofI-EziNlB4I!Qd7AoldWDn7piydBZspWdrvdolUKv+Il*ez>I*Np>uexx_7Zx z{mqO0>K86V52kW~jO>dStY}xC#>ZauDt^VsXZUfw`fL2SQ+~gCn$Jx&Anbw2u+>*d>}F0Z*~#S$t2HnZ|>H*9(7aN7K2TAEZVcnC1`Yq zb!lk8SEVA;sMqwZSLRg^W3UT$w!viD7B90+FS9LPW?Q_>ws@IuyhB0yGStkF7?0E% zKd06hnwA6TQT3q0jNP{0=&m}uYAhlaYyx~1MK5<5FGru@eK7n&y^mO(cpD`O`S`oh z!8mM~)8bsAyZ9?A&yZU9#gD|D%x``~L*hu5szgEj*a z=TS1ktspr-O76ak0?3nfaJB@vjtTFZW&681TU6F`?YDm$+Tz-=s6{FrhbkP>bof#X zQR=lP9fU4mv3<))Od}WcOiDJ1q*L-Aot@>{z&Z`XV8}Tk4IRT3P{j`@9I+Y5;_ZSo ztkFDn&V4dQumURYE3MUR$vpf*yOqi;_oEV0LLm-T0mqLMcocU?3%*8M&h$u|ht5MN z1>7RNe2O+ES;UtUV70Z53DnB0oG%lzzM`tw2QXgs{waHcFipYR3SoBH_%^JD&GCIQ z%UJ)XNVbTS?AEA^V@ob({a`$7v@pv^Y@e4Mwp-L~XUFqgHgbq4XAa!eULC}ufmNVN zg$Yp)OU_H;g;NMis-VL`FWDLIYm+hGn03Dhds~t3aJDJ;+qxa89iLfO&^>FiwGYJ1 zSOcRoTOtD!BbBNqVav${%XS?>Bm&(bprGzS6LCG}gh&Pzcs+`osBBN>KDE5?#e+zx zf(}_%aq(fNc_cH!0$j?1qCKU+Z>UO*x)RQCZ(o~#=-_c!GtOIR(gRNF%yF7W$P8FN z|2b`3^*w+@4tI0Z9fii^pvPbyE;Vs)@m=N6#05F9eb=4N=f;2zjbaZ~G9q?MvqsQ* zK;{+gzAvd8_u3hUo?=iz+1i&#pH+y+a8|-d-PVlRkgx@vljf0(&I&pW{vlzL70`^d zuBo6wMs{PU!9n-EILC-Z(RPA}fm`D9x4*;;h$zC;5l|G8l8+Z=pmK6JZj6o+8?V3y zrpAzw7g}fQZTF*bWqP;E4KF%JW$j^!dtC(BNUD$sRE|S-*)S_AfV9^&5cvb;B$neVy}&muJ#YmYhIJIzJ|1Ze!V8S{LAmyYb_TQ(_le- zy?lWMf-g3p9Lzcedr<22qtg)-Lfh@O`0n}6{ETr=8RM;>QPI5pEFdePW{OYX_}LCd zxlW-)IyM#0>UZ7xz?$JZuxu%gJ6rBUkt?CU)f>rXBcB41)Z%)BMsUAU2R(nF^=o)l zeb-$P0lQUfBMU0vA)^0+(+xii?P(w5Qc@U#&%ywT7uG_URiq3xLJHZLkkn*I0nGw{ zikKQQl|ihBv&Oi^iDGL{k`I@<3&Gvsff%g%&KN7N_de|NE~U*%8_1(H@FFhpBeWiX zbUd0tCYMKVrP1;sze$3Hnx@FM_`+QFwP`$00|T`+f+i%#ByUf!iO3GFw5L(s-U30! zw!j+V_Mq+A9JVBS%nYp)62a&~mTta5_kOCN=ep4K?g(nOIDaRtp-k0=Jx-iKpOeGu z$eg?rs&3#FLTI2-{AxHUrlD~*;?#5<60^NPKclhFTJMp!02yp}!Zzkiwz)<5vy7az zx`2Q;9rm($8+y2tP-r$5%RDt)n1rU$?k4c^O>wN7#LGA3J~k!%-V`7E62ydUX@r1_ z3l=MSl!yM^HIV0I)wA7AQ7X(VN(m#_C z>vC^|!xPJ70zbN-j7AIaH;jC8Voyd9?`I*nv;LSQM=}~sAv(7`5SZYqN1^?T5`3))74U^I@MXF$Ab0ySs3qa+En9$K`AJ-lip_(ENwaNyiIaauS4=0{tlHP6fUaa-zB& z6y-3KvIGt{l(vQ^oJ{WC7Pn$Hx0kY7SqLBSyIVJ%jp`OTOq15SzZHb3ltx^_8%Hi7 zy#PZ6U5^Ni8j#O(7RYt;IiVgq;&!PP@8$06+IU6(1qi4=MEdD;OQuykmYkazQJLO1 z1(rpiqbyJb5nEDdynyw=PH2|Uf)&ZO<#EM0(Z!WW&~nieT_%E-Fzy?V_BPJ;H^3JA z-~Xn%ffKbMamj`x{2LOCY$!+Q>!d2wSRY0+fEd11#g@)Y6hK^t z_<%El{{d;0(b1V%R=qW-PwsXp5r?B*B=XyN>48%ZjW|q(G-YDu_pu`Bh`+$&XrF7A z1&-vuAsP}T#qmf*8sTmqf5kTK7)Y2hfXmPH$yefp6A8T?7!^ zhk-dZl!Llp4N#`wF{mN%s#VYSYhVv!uuu)NaPQQ#MN}1vc9`bv@8G{91mDpjM@?t* z?wI&}#~i{P^g4d!4}Q1)&wu}q|LGt6(Lct;D;mgG@NXYpt%+n;O*Ok}70K6XqS}Q( ze*OSyNVg9L(4=wD!_+Pn+hKhO|9ZQ&_!i<&=qr!w{ULe)@&8EUhR8Had4L7J-8L1M zdtEDiAV2_Oc0}$iGjAOGy_B1eS05!{ARej9B9U@lYE5LPYMQ&(60fsnUT4i*u*TL^ z$Qku8cN)FreeBH_U^QRZJllU^Q+CS>o7gQcXe$10Rg!UhV847aui`g&>+?N)%A0;c zQ*-=L{ULsH&L7x$xBAipjls-LJ(wMecNOY_yF$S3s$k5`@jyTTmUrnV^IhGFtM}